home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
AmigActive 13
/
AACD13.ISO
/
AACD
/
Online
/
StrICQ
/
Src
/
STRICQChat.c
< prev
next >
Wrap
C/C++ Source or Header
|
2000-02-16
|
43KB
|
1,588 lines
/*
STRICQ - An Amiga, MUI Based, ICQ Clone.
Copyright (C) 1998-2000 Douglas F. McLaughlin
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Douglas F. McLaughlin - stricq@owlnet.net
*/
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <netdb.h>
#include <time.h>
#include <libraries/asl.h>
#include <libraries/asyncio.h>
#include <libraries/icq.h>
#include <bsdsocket/socketbasetags.h>
#include <sys/errno.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <proto/asyncio.h>
#include <proto/dos.h>
#include <proto/exec.h>
#include <proto/graphics.h>
#include <proto/socket.h>
#include <proto/utility.h>
#include "STRICQMUI.h"
#define MUIM_STRICQ_AddSocks TAG_USER+1
extern void Add2Log(UBYTE, ULONG, UWORD, BOOL, UWORD, char *, ULONG);
extern void AddUser2CList(struct Contact *);
extern struct Contact *GetContact(ULONG);
extern void DelSockets(UWORD);
extern char *GetNick(ULONG);
extern struct Sockets *GetSocketFmContact(struct Contact *, UBYTE);
extern struct Sockets *GetSocketFmSocket(UWORD);
extern struct Sockets *GetSocketFmPort(UWORD);
extern void HandleError(UBYTE, char *, ...);
extern LONG OpenTCPSocket(struct Contact *, UBYTE, ULONG, ULONG);
extern void PrepNewContact(struct Contact *);
extern void PrepTCPMessage(struct TCP_Message *, ULONG);
extern void revmemcpy(char *, char *, int);
extern LONG SendTCPPacket(ULONG, UWORD, char *, UWORD, UWORD);
APTR __asm AddSession(REG(a2) APTR, REG(a1) struct ChatSession *);
void __asm RemSession(REG(a2) APTR, REG(a1) struct ChatSession *);
LONG __asm CmpSession(REG(a1) struct ChatSession *, REG(a2) struct ChatSession *);
void __asm DisplaySession(REG(a2) char **, REG(a1) struct ChatSession *);
ULONG __asm ChatDispatcher(REG(a0) struct IClass *cl, REG(a2) Object *obj, REG(a1) Msg msg);
void __asm OpenChatReqWin(REG(a2) APTR);
void __asm SendChatReq(REG(a2) APTR);
void __asm EndChat(REG(a2) APTR);
void __asm ChatWinState(REG(a2) APTR);
void __asm EndAllChat(REG(a2) APTR);
void __asm SetBIU(REG(a2) APTR);
void __asm SetLocalFColor(REG(a2) APTR);
void SendChatInit(UWORD);
BOOL StartChat(struct Contact *, struct Sockets *, BOOL);
void StartRemoteChat(struct Sockets *, struct Sockets *, struct Contact *);
char *GetSessionNicks(struct Sockets *);
int recv_chat(char *, UWORD);
void DoChatMode(char *, int, UWORD);
void UpdateChatSession(struct Contact *, struct Sockets *);
struct ChatSession *GetChatSessionPort(UWORD);
ULONG CountChatPorts(struct Sockets *);
void SaveChatText(struct Contact *, struct ChatWin *, struct RemoteChatObj *);
void SendText(UWORD, char *, UWORD);
void mChatHandleEvent(struct IClass *, Object *, struct MUIP_HandleEvent *);
enum {CB_SLEEP = 0, CB_OVERRIDE, CB_X1, CB_BACK, CB_TEXT, CB_X2, CB_BOLD, CB_ITALIC, CB_UNDERLINE, CB_X3,
CB_CHATMODE, CB_X4, CB_KEYCLICK, CB_X5, CB_ACTIONS, CB_EMOTIONS};
enum {CB_COMMANDS = 0, CB_FREEZE, CB_CLEAR, CB_X10, CB_TIMEZONE};
extern char err_buf[], currentdir[], *ChatColorNames[];
extern LONG cmap[];
extern UBYTE ChatColors[16][3];
extern ULONG TCP_Seq, AsyncBuf;
extern UWORD TCPCodes[];
extern struct Colors Pens;
extern struct ObjApp *app;
struct MUIP_STRICQ_AddSocks {
ULONG MethodID;
struct Sockets *Socks;
};
APTR __asm AddSession(REG(a2) APTR pool, REG(a1) struct ChatSession *chat)
{
struct ChatSession *newchat = NULL;
if (!(newchat = AllocPooled(pool,sizeof(struct ChatSession)))) return(NULL);
strcpy(newchat->Session,chat->Session);
newchat->ChatListen = chat->ChatListen;
return(newchat);
}
void __asm RemSession(REG(a2) APTR pool, REG(a1) struct ChatSession *chat)
{
FreePooled(pool,chat,sizeof(struct ChatSession));
return;
}
LONG __asm CmpSession(REG(a1) struct ChatSession *a1, REG(a2) struct ChatSession *a2)
{
if (a1->ChatListen < a2->ChatListen) return(-1);
if (a1->ChatListen > a2->ChatListen) return(1);
return(0);
}
void __asm DisplaySession(REG(a2) char **array, REG(a1) struct ChatSession *chat)
{
static char buf[10];
if (chat) {
sprintf(buf,"%d",chat->ChatListen);
*array++ = buf;
*array = chat->Session;
}
else {
*array++ = "Port";
*array = "Current Chat Sessions";
}
return;
}
void __asm OpenChatReqWin(REG(a2) APTR obj)
{
static char nick[21];
ULONG uin, total;
get(obj,MUIA_UserData,&uin);
strcpy(nick,GetNick(uin));
set(app->WI_ChatReqOut,MUIA_Window_Title,nick);
set(app->BT_SendChat,MUIA_UserData,uin);
set(app->BT_JoinChat,MUIA_UserData,uin);
get(app->LV_Sessions,MUIA_NList_Entries,&total);
if (total == 0) set(app->BT_JoinChat,MUIA_Disabled,TRUE);
else set(app->BT_JoinChat,MUIA_Disabled,FALSE);
set(app->WI_ChatReqOut,MUIA_Window_Open,TRUE);
return;
}
void __asm SendChatReq(REG(a2) APTR obj)
{
char *msg, *sess_nicks, *TCP_Buf = NULL;
LONG sel;
ULONG id, Seq;
UWORD len, RevLen, ret, session = 0;
struct ChatSession *chat;
struct Contact *user;
struct TCP_Message TCPMsg;
sess_nicks = LINE;
if (obj == app->BT_JoinChat) {
get(app->LV_Sessions,MUIA_NList_Active,&sel);
if (sel == MUIV_NList_Active_Off) {
HandleError(DBG_OTH_FATL,"You must choose a chat session to 'Join'.");
return;
}
DoMethod(app->LV_Sessions,MUIM_NList_GetEntry,sel,&chat);
if (chat) {
session = chat->ChatListen;
sess_nicks = chat->Session;
}
}
get(obj,MUIA_UserData,&id);
if (!(user = GetContact(id))) return;
if (!user->UWin) return;
user->ChatListen = session;
if (session) user->ConnectMe = TRUE;
get(app->TI_ChatReason,MUIA_Textinput_Contents,&msg);
set(app->WI_ChatReqOut,MUIA_Window_Open,FALSE);
TCPMsg.Command = TCP_MESSAGE;
TCPMsg.Type = MSG_CHAT;
TCPMsg.MsgCommand = TCP_MSG_REAL;
PrepTCPMessage(&TCPMsg,id);
TCPMsg.Message = msg;
TCPMsg.Chat_Session = sess_nicks;
TCPMsg.Chat_RevPort = TCPMsg.Chat_Port = user->ChatListen;
TCPMsg.Chat_X2 = 0;
len = TCP_CreateMsgPacket(&TCPMsg,&TCP_Buf,&Seq,&RevLen);
if (!(ret = SendTCPPacket(id,TCP_MESSAGE,TCP_Buf,len,RevLen))) {
HandleError(DBG_TCP_ERRS,"Could not send Chat Request to %s.",user->Nick);
TCP_FreeMsgPacket(TCP_Buf);
return;
}
set(app->TI_ChatReason,MUIA_Textinput_Contents,NULL);
if (ret == -1) Add2Log(LOG_CLIENT,Seq,TCP_MESSAGE,FALSE,len,TCP_Buf,id);
else Add2Log(LOG_CLIENT,Seq,TCP_MESSAGE,FALSE,0,NULL,id);
TCP_FreeMsgPacket(TCP_Buf);
return;
}
void SendChatInit(UWORD sock)
{
char buf[50], *nick;
UWORD len, revlen;
struct Contact *user;
struct Sockets *socks;
struct TCP_ChatInit Init;
if (!(socks = GetSocketFmSocket(sock))) return;
if (!(user = GetContact(socks->UIN))) return;
get(app->STR_ICQUIN,MUIA_String_Integer,&Init.UIN);
get(app->STR_Nick,MUIA_String_Contents,&nick);
Init.HandShake = TCP_CHAT_HANDSHAKE;
Init.HiVersion = TCP_CHAT_VER_CURRENT;
strcpy(Init.Nick,nick);
Init.RevPort = user->ChatListen;
Init.TextColor = 0x00FFFFFF;
Init.BackColor = 0x00000000;
Init.X1 = 0x00;
HandleError(DBG_TCP_DBUG,"SendChatInit()");
len = TCP_CreateChatPacket(TCP_CHAT_1,&Init,buf,&revlen);
send(sock,(char *)&revlen,2,0);
send(sock,buf,len,0);
socks->Timehack = time(NULL);
socks->ConnectPort = user->ChatListen;
return;
}
void ParseChatPkt(char *buf, int len, UWORD sock)
{
APTR Data = NULL;
char cbuf[1024];
int i;
UBYTE Cmd;
ULONG opt = 1, sess_count;
UWORD RevLen, Len;
struct Contact *user, User;
struct Sockets *socks, *sock2, *primesocks;
struct TCP_Init Init;
if (socks = GetSocketFmSocket(sock)) {
user = GetContact(socks->UIN);
socks->Timehack = time(NULL);
}
PrintHex(DBG_TCP_PKTS,"Chat packet",buf,len);
if (!socks->HadInit) {
if (!TCP_ParseTCPInit(&Init,buf)) return;
if (!(user = GetContact(Init.UIN))) {
PrepNewContact(&User);
User.UIN = Init.UIN;
sprintf(cbuf,"%ld",Init.UIN);
User.Nick = cbuf;
User.Status = STATUS_NEWUIN;
User.CanTCP = Init.TCP_Flag;
AddUser2CList(&User);
user = GetContact(Init.UIN);
}
user->ChatListen = socks->ConnectPort;
socks->TCP_Version = Init.Version;
socks->TCP_Revision = Init.X1;
socks->TCP_Listen_Msg_Port = Init.TCP_MsgPort;
socks->TCP_Listen_Other_Port = Init.TCP_Chat_File_Port;
socks->UIN = user->UIN;
socks->TCP_Flag = Init.TCP_Flag;
socks->HadInit = TRUE;
DoMethod(app->LV_SockList,MUIM_NList_Redraw,MUIV_NList_Redraw_All);
return;
}
primesocks = GetSocketFmPort(user->ChatListen);
Cmd = TCP_ParseChatPacket(&Data,buf);
switch(Cmd) {
case TCP_CHAT_1: {
char *nick;
// int i;
ULONG total;
// struct Sockets *sock2;
struct TCP_ChatInit *Init = Data;
struct TCP_ChatTwo Two;
struct TCP_ChatTwo_Ext *ext_p1, *ext_p2;
socks->TCP_ChatHandShake = Init->HandShake;
get(app->STR_ICQUIN,MUIA_String_Integer,&total);
get(app->STR_Nick,MUIA_String_Contents,&nick);
Two.HandShake = TCP_CHAT_HANDSHAKE;
Two.UIN = total;
strcpy(Two.Nick,nick);
Two.TextColor = 0x00FFFFFF;
Two.BackColor = 0x00000000;
Two.Version = TCP_VERSION_CURRENT;
Two.X1 = TCP_REVISION_CURRENT;
Two.Port = socks->ConnectPort;
Two.IP = socks->LocalAddr.sin_addr.s_addr;
Two.RealIP = socks->LocalAddr.sin_addr.s_addr;
Two.TCP_Flag = TCP_FLAG_CAPABLE;
Two.X2 = 0x6A6C;
Two.FontSize = 0x00000008;
Two.FontFamily = 0x00000000;
strcpy(Two.FontName,"Courier");
Two.X3 = 0x00;
Two.X4 = 0x02;
Two.Ext.Next = NULL;
ext_p2 = &Two.Ext;
sess_count = CountChatPorts(primesocks);
Two.Count = sess_count-1;
if (sess_count > 1) {
get(app->LV_SockList,MUIA_NList_Entries,&total);
for(i = 0; i < total; i++) {
DoMethod(app->LV_SockList,MUIM_NList_GetEntry,i,&sock2);
if (sock2) {
if (sock2->ConnectPort == primesocks->Port && sock2 != socks && sock2 != primesocks) {
HandleError(DBG_TCP_DBUG,"Adding socket %d to the TCP_CHAT_2 struct",sock2->Socket);
if (!(ext_p1 = (struct TCP_ChatTwo_Ext *)AllocVec(sizeof(struct TCP_ChatTwo_Ext),MEMF_CLEAR))) break;
ext_p2->Next = ext_p1;
ext_p1->Next = NULL;
ext_p1->Version = sock2->TCP_Version;
ext_p1->X1 = sock2->TCP_Revision;
ext_p1->Port = sock2->TCP_Listen_Other_Port;
ext_p1->UIN = sock2->UIN;
ext_p1->IP = sock2->Address.sin_addr.s_addr;
ext_p1->RealIP = sock2->Address.sin_addr.s_addr;
ext_p1->RevPort = sock2->TCP_Listen_Other_Port;
ext_p1->TCP_Flag = sock2->TCP_Flag;
ext_p1->X2 = sock2->TCP_ChatData;
ext_p1->HandShake = sock2->TCP_ChatHandShake;
ext_p2 = ext_p1;
}
}
}
}
HandleError(DBG_TCP_DBUG,"About to create TCP_CHAT_2");
Len = TCP_CreateChatPacket(TCP_CHAT_2,&Two,cbuf,&RevLen);
send(sock,(char *)&RevLen,2,0);
send(sock,cbuf,Len,0);
if (Two.Ext.Next) {
ext_p1 = Two.Ext.Next;
while(ext_p1) {
ext_p2 = ext_p1->Next;
FreeVec(ext_p1);
ext_p1 = ext_p2;
}
Two.Ext.Next = NULL;
}
break;
}
case TCP_CHAT_2: {
struct TCP_ChatThree Three;
struct TCP_ChatTwo *Two = Data;
struct TCP_ChatTwo_Ext *ext_p1, *ext_p2;
socks->TCP_Version = Two->Version;
socks->TCP_Revision = Two->X1;
socks->TCP_Listen_Other_Port = Two->Port;
socks->TCP_Flag = Two->TCP_Flag;
socks->TCP_ChatData = Two->X2;
socks->TCP_ChatHandShake = Two->HandShake;
ext_p2 = &Two->Ext;
while(ext_p1 = ext_p2->Next) {
struct Contact *user2;
if (!(user2 = GetContact(ext_p1->UIN))) {
PrepNewContact(&User);
User.UIN = ext_p1->UIN;
sprintf(cbuf,"%ld",ext_p1->UIN);
User.Nick = cbuf;
User.Status = STATUS_NEWUIN;
User.CanTCP = ext_p1->TCP_Flag;
AddUser2CList(&User);
user2 = GetContact(ext_p1->UIN);
}
if (!user2->ChatListen) {
user2->ChatListen = socks->ConnectPort;
user2->IP = ext_p1->IP;
user2->RealIP = ext_p1->RealIP;
HandleError(DBG_TCP_DBUG,"Also adding %s to multichat.",user2->Nick);
if (!OpenTCPSocket(user2,SOCK_CHAT,user2->IP,ext_p1->RevPort)) {
if (!OpenTCPSocket(user2,SOCK_CHAT,user2->RealIP,ext_p1->RevPort)) HandleError(DBG_TCP_ERRS,"Could not open a chat connection to %s.",user->Nick);
}
}
ext_p2 = ext_p1;
}
Three.Version = TCP_VERSION_CURRENT;
Three.X1 = TCP_REVISION_CURRENT;
Three.Port = socks->ConnectPort;
Three.IP = socks->LocalAddr.sin_addr.s_addr;
Three.RealIP = socks->LocalAddr.sin_addr.s_addr;
Three.TCP_Flag = TCP_FLAG_CAPABLE;
Three.X2 = 0x6A6C;
Three.FontSize = 0x00000008;
Three.FontFamily = 0x00000000;
strcpy(Three.FontName,"Courier");
Three.X3 = 0x0002;
HandleError(DBG_TCP_DBUG,"About to create TCP_CHAT_3");
Len = TCP_CreateChatPacket(TCP_CHAT_3,&Three,cbuf,&RevLen);
send(sock,(char *)&RevLen,2,0);
send(sock,cbuf,Len,0);
if (!primesocks->CWin) {
if (!StartChat(user,primesocks,FALSE)) {
DelSockets(sock);
break;
}
}
StartRemoteChat(socks,primesocks,user);
setsockopt(sock,IPPROTO_TCP,TCP_NODELAY,&opt,sizeof(opt));
socks->ChatMode = user;
break;
}
case TCP_CHAT_3: {
struct TCP_ChatThree *Three = Data;
socks->TCP_Version = Three->Version;
socks->TCP_Revision = Three->X1;
socks->TCP_Listen_Other_Port = Three->Port;
socks->TCP_Flag = Three->TCP_Flag;
socks->TCP_ChatData = Three->X2;
send(sock,"\004",1,0);
send(sock,"\003",1,0);
if (!primesocks->CWin) {
if (!StartChat(user,primesocks,FALSE)) {
DelSockets(sock);
break;
}
}
StartRemoteChat(socks,primesocks,user);
socks->ChatMode = user;
setsockopt(sock,IPPROTO_TCP,TCP_NODELAY,&opt,sizeof(opt));
break;
}
default:
PrintHex(DBG_TCP_ERRS,"Unknown Chat Init packet",buf,len);
}
if (Data) FreeVec(Data);
return;
}
BOOL StartChat(struct Contact *user, struct Sockets *primesocks, BOOL open)
{
char *nick;
static char Image_fl[MAXNAMLEN], Select_fl[MAXNAMLEN], Ghost_fl[MAXNAMLEN];
time_t t;
struct ChatWin *CWin;
struct Sockets *socks;
static struct MUIP_Toolbar_Description TBDesc[] = {
{TDT_BUTTON, 's' , TDF_GHOSTED, "Sleep" , "Sets your Chat Mode\nstatus to 'Away'" , 0},
{TDT_BUTTON, 'o' , TDF_GHOSTED, "Override" , "Overrides the other user's\nfont/color prefs", 0},
{TDT_SPACE , NULL, NULL , NULL , NULL , 0},
{TDT_BUTTON, NULL, TDF_GHOSTED, "Back" , "Set the background color\n(Has no effect)" , 0},
{TDT_BUTTON, 'f' , NULL , "Text" , "Set the current font color" , 0},
{TDT_SPACE , NULL, NULL , NULL , NULL , 0},
{TDT_BUTTON, 'b' , TDF_TOGGLE , "Bold" , "Set text to Bold" , 0},
{TDT_BUTTON, 'i' , TDF_TOGGLE , "Italic" , "Set text to Italic" , 0},
{TDT_BUTTON, 'u' , TDF_TOGGLE , "Underline", "Set text to Underline" , 0},
{TDT_SPACE , NULL, NULL , NULL , NULL , 0},
{TDT_BUTTON, 'w' , TDF_GHOSTED, "Chat Mode", "Set window mode to either\nSplit or IRC" , 0},
{TDT_SPACE , NULL, NULL , NULL , NULL , 0},
{TDT_BUTTON, 'c' , TDF_GHOSTED, "Keyclick" , "Toggle keyclick on/off" , 0},
{TDT_SPACE , NULL, NULL , NULL , NULL , 0},
{TDT_BUTTON, 'a' , TDF_GHOSTED, "Actions" , "Send an action line" , 0},
{TDT_BUTTON, 'e' , TDF_GHOSTED, "Emotions" , "Send an emotion line" , 0},
{TDT_BUTTON, 'm' , TDF_GHOSTED, "Smileys" , "Send a smiley" , 0},
{TDT_END, NULL, NULL, NULL, NULL, NULL},
};
HandleError(DBG_TCP_DBUG,"StartChat()");
socks = GetSocketFmContact(user,SOCK_CHAT);
if (primesocks->CWin) {
if (open) set(primesocks->CWin->WI_ChatWin,MUIA_Window_Open,TRUE);
return(TRUE);
}
if (!(CWin = (struct ChatWin *)AllocVec(sizeof(struct ChatWin),MEMF_CLEAR))) {
HandleError(DBG_OTH_FATL,"Failed to AllocVec %d bytes (struct ChatWin)",sizeof(struct ChatWin));
return(FALSE);
}
sprintf(Image_fl,"%sImages/ChatBarN.iff",currentdir);
sprintf(Select_fl,"%sImages/ChatBarS.iff",currentdir);
sprintf(Ghost_fl,"%sImages/ChatBarG.iff",currentdir);
get(app->STR_Nick,MUIA_String_Contents,&nick);
t = time(NULL);
strcpy(CWin->Title,nick);
sprintf(CWin->LocalTime,"Local Time: %.5s",ctime(&t)+11);
CWin->SC_ScrollBar = ScrollbarObject, End;
CWin->WI_ChatWin = WindowObject,
MUIA_Window_Title, CWin->Title,
MUIA_Window_ID, user->UIN | 0x20000000,
MUIA_UserData, user->UIN,
WindowContents, VGroup,
Child, ScrollgroupObject,
MUIA_Scrollgroup_FreeVert, FALSE,
MUIA_Scrollgroup_Contents, HGroupV,
// MUIA_Frame, MUIV_Frame_Virtual,
Child, CWin->TB_ChatBar = ToolbarObject,
MUIA_Toolbar_Description, TBDesc,
MUIA_Toolbar_ImageType, MUIV_Toolbar_ImageType_File,
MUIA_Toolbar_ImageNormal, Image_fl,
MUIA_Toolbar_ImageSelect, Select_fl,
MUIA_Toolbar_ImageGhost, Ghost_fl,
MUIA_ShortHelp, TRUE,
End,
Child, CWin->POP_FColors = PopobjectObject,
MUIA_Popstring_String, VSpace(0),
MUIA_Popstring_Button, VSpace(0),
MUIA_Popobject_ObjStrHook, &SetLocalFColorHook,
MUIA_Popobject_Object, CWin->LV_FColorList = NListviewObject,
MUIA_NListview_NList, NListObject,
MUIA_Frame, MUIV_Frame_String,
MUIA_NList_PrivateData, user->UIN,
MUIA_NList_ConstructHook, MUIV_NList_ConstructHook_String,
MUIA_NList_DestructHook, MUIV_NList_DestructHook_String,
MUIA_NList_SourceArray, ChatColorNames,
MUIA_NList_AdjustWidth, TRUE,
MUIA_NList_AdjustHeight, TRUE,
End,
End,
End,
Child, Label("Font"),
Child, CWin->POP_ChatFont = PopaslObject,
MUIA_Popasl_Type, ASL_FontRequest,
MUIA_Popstring_String, CWin->STR_ChatFont = String("",80),
MUIA_Popstring_Button, PopButton(MUII_PopUp),
ASLFO_TitleText, "Please select a font...",
End,
End,
End,
Child, VGroup,
MUIA_Frame, MUIV_Frame_Group,
Child, HGroup,
Child, TextObject,
MUIA_Text_Contents, "My Chat view",
End,
Child, CWin->TX_LocalTime = TextObject,
MUIA_Text_PreParse, "\033r",
MUIA_Text_Contents, CWin->LocalTime,
End,
End,
Child, HGroup,
MUIA_Group_Spacing, 0,
Child, CWin->TE_ChatLocal = NewObject(mcc_Chat->mcc_Class,NULL,
MUIA_Frame, MUIV_Frame_String,
// MUIA_Font, MUIV_Font_Tiny,
MUIA_CycleChain, TRUE,
MUIA_TextEditor_ExportHook, MUIV_TextEditor_ExportHook_Plain,
MUIA_TextEditor_Slider, CWin->SC_ScrollBar,
MUIA_TextEditor_ColorMap, cmap,
End,
Child, CWin->SC_ScrollBar,
End,
End,
Child, BalanceObject, End,
Child, CWin->GP_ChatGroups = HGroup,
Child, CWin->RT_Dummy = RectangleObject, End,
End,
End,
End;
if (!CWin->WI_ChatWin) {
HandleError(DBG_OTH_FATL,"Could not create the initial chat window.");
FreeVec(CWin);
CWin = NULL;
return(FALSE);
}
DoMethod(app->App,OM_ADDMEMBER,CWin->WI_ChatWin);
DoMethod(CWin->TE_ChatLocal,MUIM_STRICQ_AddSocks,primesocks);
DoMethod(CWin->WI_ChatWin,MUIM_Notify,MUIA_Window_CloseRequest,TRUE,CWin->WI_ChatWin,2,
MUIM_CallHook,&EndAllChatHook);
DoMethod(CWin->WI_ChatWin,MUIM_Notify,MUIA_Window_Activate,MUIV_EveryTime,CWin->WI_ChatWin,2,
MUIM_CallHook,&ChatWinStateHook);
DoMethod(CWin->TB_ChatBar,MUIM_Toolbar_Notify,CB_BOLD,MUIV_Toolbar_Notify_Pressed,MUIV_EveryTime,CWin->TE_ChatLocal,3,
MUIM_Set,MUIA_TextEditor_StyleBold,MUIV_TriggerValue);
DoMethod(CWin->TB_ChatBar,MUIM_Toolbar_Notify,CB_BOLD,MUIV_Toolbar_Notify_Pressed,MUIV_EveryTime,CWin->WI_ChatWin,2,
MUIM_CallHook,&SetBIUHook);
DoMethod(CWin->TB_ChatBar,MUIM_Toolbar_Notify,CB_ITALIC,MUIV_Toolbar_Notify_Pressed,MUIV_EveryTime,CWin->TE_ChatLocal,3,
MUIM_Set,MUIA_TextEditor_StyleItalic,MUIV_TriggerValue);
DoMethod(CWin->TB_ChatBar,MUIM_Toolbar_Notify,CB_ITALIC,MUIV_Toolbar_Notify_Pressed,MUIV_EveryTime,CWin->WI_ChatWin,2,
MUIM_CallHook,&SetBIUHook);
DoMethod(CWin->TB_ChatBar,MUIM_Toolbar_Notify,CB_UNDERLINE,MUIV_Toolbar_Notify_Pressed,MUIV_EveryTime,CWin->TE_ChatLocal,3,
MUIM_Set,MUIA_TextEditor_StyleUnderline,MUIV_TriggerValue);
DoMethod(CWin->TB_ChatBar,MUIM_Toolbar_Notify,CB_UNDERLINE,MUIV_Toolbar_Notify_Pressed,MUIV_EveryTime,CWin->WI_ChatWin,2,
MUIM_CallHook,&SetBIUHook);
DoMethod(CWin->TB_ChatBar,MUIM_Toolbar_Notify,CB_TEXT,MUIV_Toolbar_Notify_Pressed,FALSE,CWin->POP_FColors,1,
MUIM_Popstring_Open);
DoMethod(CWin->LV_FColorList,MUIM_Notify,MUIA_NList_EntryClick,MUIV_EveryTime,CWin->POP_FColors,2,
MUIM_Popstring_Close,TRUE);
set(CWin->WI_ChatWin,MUIA_Window_ActiveObject,CWin->TE_ChatLocal);
if (open) set(CWin->WI_ChatWin,MUIA_Window_Open,TRUE);
primesocks->CWin = CWin;
return(TRUE);
}
ULONG __asm ChatDispatcher(REG(a0) struct IClass *cl, REG(a2) Object *obj, REG(a1) Msg msg)
{
int i;
switch(msg->MethodID) {
case MUIM_Setup: {
struct ChatData *data = INST_DATA(cl,obj);
data->Events.ehn_Priority = 0;
data->Events.ehn_Flags = 0;
data->Events.ehn_Events = IDCMP_VANILLAKEY;
data->Events.ehn_Object = obj;
data->Events.ehn_Class = cl;
DoMethod(_win(obj),MUIM_Window_AddEventHandler,&data->Events);
HandleError(DBG_TCP_DBUG,"Finished MUIM_Setup");
break;
}
case MUIM_Show:
for(i = 0; i < NUM_CHAT_COLORS; i++) cmap[i] = MUIPEN(Pens.ChatColors[i]);
break;
case MUIM_HandleEvent:
mChatHandleEvent(cl,obj,(struct MUIP_HandleEvent *)msg);
break;
case MUIM_Cleanup: {
struct ChatData *data = INST_DATA(cl,obj);
DoMethod(_win(obj),MUIM_Window_RemEventHandler,&data->Events);
HandleError(DBG_TCP_DBUG,"Finished MUIM_Cleanup");
break;
}
case MUIM_STRICQ_AddSocks: {
struct ChatData *data = INST_DATA(cl,obj);
data->Socks = ((struct MUIP_STRICQ_AddSocks *)msg)->Socks;
HandleError(DBG_TCP_DBUG,"MUIM_STRICQ_AddSocks");
return(TRUE);
}
//default:
// HandleError(DBG_TCP_DBUG,"Unknown ChatDispatcher Method");
}
return(DoSuperMethodA(cl,obj,msg));
}
void mChatHandleEvent(struct IClass *cl, Object *obj, struct MUIP_HandleEvent *msg)
{
BOOL flag = FALSE, *bold, *italic, *underline;
char key[2], text[16], *notifycmd;
LONG pen;
struct Sockets *primesocks;
struct ChatData *data = INST_DATA(cl,obj);
//HandleError(DBG_TCP_DBUG,"mChatHandleEvent()");
primesocks = data->Socks;
key[1] = '\0';
if (msg->imsg) {
switch(msg->imsg->Class) {
case IDCMP_VANILLAKEY:
set(primesocks->CWin->WI_ChatWin,MUIA_Window_ActiveObject,primesocks->CWin->TE_ChatLocal);
DoMethod(primesocks->CWin->TE_ChatLocal,MUIM_TextEditor_ARexxCmd,"POSITION EOF");
key[0] = (char)msg->imsg->Code;
switch(key[0]) {
case 0x07:
flag = TRUE;
get(app->STR_ChatBeep,MUIA_String_Contents,¬ifycmd);
if (strlen(notifycmd) > 0) System(notifycmd,NULL);
else DisplayBeep(NULL);
break;
case 0x08:
flag = TRUE;
DoMethod(primesocks->CWin->TE_ChatLocal,MUIM_TextEditor_ARexxCmd,"BACKSPACE");
break;
case 0x0d:
flag = TRUE;
key[0] = '\n';
DoMethod(primesocks->CWin->TE_ChatLocal,MUIM_TextEditor_InsertText,key,MUIV_TextEditor_InsertText_Bottom);
key[0] = '\x0d';
break;
default:
if ((UBYTE)key[0] >= (UBYTE)' ') {
flag = TRUE;
text[0] = '\0';
get(primesocks->CWin->TE_ChatLocal,MUIA_TextEditor_StyleBold,&bold);
get(primesocks->CWin->TE_ChatLocal,MUIA_TextEditor_StyleItalic,&italic);
get(primesocks->CWin->TE_ChatLocal,MUIA_TextEditor_StyleUnderline,&underline);
get(primesocks->CWin->TE_ChatLocal,MUIA_TextEditor_Pen,&pen);
if (bold) strcat(text,"\33b");
if (italic) strcat(text,"\33i");
if (underline) strcat(text,"\33u");
sprintf(text,"%s\33p[%ld]%s\33n",text,pen,key);
DoMethod(primesocks->CWin->TE_ChatLocal,MUIM_TextEditor_InsertText,text,MUIV_TextEditor_InsertText_Bottom);
}
break;
}
break;
}
}
if (flag) SendText(primesocks->Port,key,1);
return;
}
void StartRemoteChat(struct Sockets *socks, struct Sockets *primesocks, struct Contact *user)
{
BOOL *open;
static char Image_fl[MAXNAMLEN], Select_fl[MAXNAMLEN], Ghost_fl[MAXNAMLEN];
time_t t;
struct RemoteChatObj *RCObj;
static struct MUIP_Toolbar_Description RTBDesc[] = {
{TDT_BUTTON, NULL, TDF_GHOSTED, "Commands" , "Additional commands to\nperform with this UIN", 0},
{TDT_BUTTON, NULL, TDF_TOGGLE , "Freeze" , "Freeze incoming text" , 0},
{TDT_BUTTON, NULL, NULL , "Clear" , "Clears the text" , 0},
{TDT_SPACE , NULL, NULL , NULL , NULL , 0},
{TDT_BUTTON, NULL, TDF_GHOSTED, "Timezone" , "Sets remote user's timezone" , 0},
{TDT_END, NULL, NULL, NULL, NULL, NULL},
};
HandleError(DBG_TCP_DBUG,"StartRemoteChat()");
get(primesocks->CWin->WI_ChatWin,MUIA_Window_Open,&open);
if (open) DoMethod(primesocks->CWin->GP_ChatGroups,MUIM_Group_InitChange);
if (socks->RCObj) HandleError(DBG_TCP_ERRS,"Found a RemoteChatObj in the beginning of StartRemoteChat(). Please report this.");
if (!(RCObj = (struct RemoteChatObj *)AllocVec(sizeof(struct RemoteChatObj),MEMF_CLEAR))) {
HandleError(DBG_OTH_FATL,"Failed to AllocVec %d bytes (struct RemoteChatObj)",sizeof(struct RemoteChatObj));
return;
}
sprintf(Image_fl,"%sImages/ChatBar2N.iff",currentdir);
sprintf(Select_fl,"%sImages/ChatBar2S.iff",currentdir);
sprintf(Ghost_fl,"%sImages/ChatBar2G.iff",currentdir);
t = time(NULL);
strcpy(RCObj->Nick,user->Nick);
sprintf(RCObj->RemoteTime,"Remote Time: %.5s",ctime(&t)+11);
RCObj->SC_ScrollBar = ScrollbarObject, End;
RCObj->GP_RemoteObj = VGroup,
MUIA_Frame, MUIV_Frame_Group,
MUIA_UserData, user->UIN,
Child, HGroup,
Child, RCObj->TX_Nick = TextObject,
MUIA_Text_Contents, RCObj->Nick,
MUIA_Weight, 0,
End,
Child, RCObj->TB_RemoteChatBar = ToolbarObject,
MUIA_Toolbar_Description, RTBDesc,
MUIA_Toolbar_ImageType, MUIV_Toolbar_ImageType_File,
MUIA_Toolbar_ImageNormal, Image_fl,
MUIA_Toolbar_ImageSelect, Select_fl,
MUIA_Toolbar_ImageGhost, Ghost_fl,
MUIA_ShortHelp, TRUE,
MUIA_HorizDisappear, 2,
End,
Child, RCObj->TX_RemoteTime = TextObject,
MUIA_Text_PreParse, "\033r",
MUIA_Text_Contents, RCObj->RemoteTime,
MUIA_HorizDisappear, 1,
End,
End,
Child, HGroup,
MUIA_Group_Spacing, 0,
Child, RCObj->TE_ChatRemote = TextEditorObject,
MUIA_Frame, MUIV_Frame_String,
// MUIA_Font, MUIV_Font_Tiny,
MUIA_TextEditor_Slider, RCObj->SC_ScrollBar,
MUIA_TextEditor_ColorMap, cmap,
End,
Child, RCObj->SC_ScrollBar,
End,
End;
if (!RCObj->GP_RemoteObj) {
HandleError(DBG_OTH_FATL,"Could not create a Remote Chat Object");
FreeVec(RCObj);
RCObj = NULL;
return;
}
set(primesocks->CWin->RT_Dummy,MUIA_ShowMe,FALSE);
DoMethod(primesocks->CWin->GP_ChatGroups,OM_ADDMEMBER,RCObj->GP_RemoteObj);
if (open) DoMethod(primesocks->CWin->GP_ChatGroups,MUIM_Group_ExitChange);
else set(primesocks->CWin->WI_ChatWin,MUIA_Window_Open,TRUE);
get(primesocks->CWin->WI_ChatWin,MUIA_Window_Open,&open);
if (!open) HandleError(DBG_OTH_FATL,"Chat window could not be opened!");
socks->RCObj = RCObj;
DoMethod(RCObj->TB_RemoteChatBar,MUIM_Toolbar_Notify,CB_FREEZE,MUIV_Toolbar_Notify_Pressed,MUIV_EveryTime,RCObj->TE_ChatRemote,3,
MUIM_Set,MUIA_TextEditor_Quiet,MUIV_TriggerValue);
DoMethod(RCObj->TB_RemoteChatBar,MUIM_Toolbar_Notify,CB_CLEAR,MUIV_Toolbar_Notify_Pressed,FALSE,RCObj->TE_ChatRemote,1,
MUIM_TextEditor_ClearText);
UpdateChatSession(user,primesocks);
return;
}
char *GetSessionNicks(struct Sockets *primesocks)
{
static char nicks[256];
char *nick;
int i;
ULONG total;
struct Sockets *socks;
HandleError(DBG_TCP_DBUG,"GetSessionNicks(%d)",primesocks->Port);
get(app->LV_SockList,MUIA_NList_Entries,&total);
if (total < 1) return(NULL);
get(app->STR_Nick,MUIA_String_Contents,&nick);
strcpy(nicks,nick);
for(i = 0; i < total; i++) {
DoMethod(app->LV_SockList,MUIM_NList_GetEntry,i,&socks);
if (socks) {
if (socks->ConnectPort == primesocks->Port && socks != primesocks) {
HandleError(DBG_TCP_DBUG,"Socket %d has ConnectPort %d",socks->Socket,socks->ConnectPort);
sprintf(nicks,"%s, %s",nicks,GetNick(socks->UIN));
}
}
}
if (strlen(nicks) == 0) return(NULL);
return(nicks);
}
int recv_chat(char *buf, UWORD sock)
{
int i;
ULONG err;
i = recv(sock,buf,TCPBUFLEN,0);
if (i == 0) return(-1);
if (i < 0) {
switch(err = Errno()) {
case EWOULDBLOCK:
case EBADF:
i = 0;
break;
default:
SocketBaseTags(SBTM_GETREF(SBTC_ERRNOSTRPTR),&err,TAG_DONE);
HandleError(DBG_TCP_ERRS,"Error on chat socket %d: %s\n",sock,(char *)err);
}
}
return(i);
}
void DoChatMode(char *buf, int len, UWORD sock)
{
BOOL *bold, *italic, *underline;
char *notifycmd, key[2], text[16], *font;
int i;
LONG pen;
UWORD flen;
struct Sockets *socks;
socks = GetSocketFmSocket(sock);
PrintHex(DBG_TCP_PKTS,"Chat mode data",buf,len);
key[1] = '\0';
for(i = 0; i<len; i++) {
DoMethod(socks->RCObj->TE_ChatRemote,MUIM_TextEditor_ARexxCmd,"POSITION EOF");
switch(buf[i]) {
case 0x07: //Beep
get(app->STR_ChatBeep,MUIA_String_Contents,¬ifycmd);
if (strlen(notifycmd) > 0) System(notifycmd,NULL);
else DisplayBeep(NULL);
break;
case 0x12: //Font Size
i += 4;
break;
case 0x01: //Background Color
i += 4;
break;
case TCP_CHAT_CMD_FCOLOR: {
int j;
for(j = 0; j < NUM_CHAT_COLORS; j++) {
if ((UBYTE)buf[i+1] == ChatColors[j][0] && (UBYTE)buf[i+2] == ChatColors[j][1] && (UBYTE)buf[i+3] == ChatColors[j][2]) break;
}
if (j == NUM_CHAT_COLORS) j = -1;
set(socks->RCObj->TE_ChatRemote,MUIA_TextEditor_Pen,j+1);
i += 4;
break;
}
case TCP_CHAT_CMD_STYLE: {
struct TCP_ChatCmdStyle Style;
Style.Bold = (buf[++i]&TCP_CHATF_BOLD?TRUE:FALSE);
Style.Italic = (buf[i]&TCP_CHATF_ITALIC?TRUE:FALSE);
Style.Underline = (buf[i]&TCP_CHATF_UNDERLINE?TRUE:FALSE);
set(socks->RCObj->TE_ChatRemote,MUIA_TextEditor_StyleBold,Style.Bold);
set(socks->RCObj->TE_ChatRemote,MUIA_TextEditor_StyleItalic,Style.Italic);
set(socks->RCObj->TE_ChatRemote,MUIA_TextEditor_StyleUnderline,Style.Underline);
i += 3;
break;
}
case 0x04: //Activate window
case 0x03: //De-Activate window
break;
case 0x0b: //End Chat Mode
EndChat(socks->RCObj->GP_RemoteObj);
return;
case 0x10: //Change Font Name
i++;
revmemcpy((char *)&flen,buf+i,2); i += 2;
font = buf+i; i += (flen+1);
break;
case 0x08: //Backspace
DoMethod(socks->RCObj->TE_ChatRemote,MUIM_TextEditor_ARexxCmd,"BACKSPACE");
break;
case 0x0d: //Return
key[0] = '\n';
DoMethod(socks->RCObj->TE_ChatRemote,MUIM_TextEditor_InsertText,key,MUIV_TextEditor_InsertText_Bottom);
break;
default: //All remaining text
key[0] = buf[i];
if ((UBYTE)key[0] >= (UBYTE)' ') {
text[0] = '\0';
get(socks->RCObj->TE_ChatRemote,MUIA_TextEditor_StyleBold,&bold);
get(socks->RCObj->TE_ChatRemote,MUIA_TextEditor_StyleItalic,&italic);
get(socks->RCObj->TE_ChatRemote,MUIA_TextEditor_StyleUnderline,&underline);
get(socks->RCObj->TE_ChatRemote,MUIA_TextEditor_Pen,&pen);
if (bold) strcat(text,"\33b");
if (italic) strcat(text,"\33i");
if (underline) strcat(text,"\33u");
sprintf(text,"%s\33p[%ld]%s\33n",text,pen,key);
DoMethod(socks->RCObj->TE_ChatRemote,MUIM_TextEditor_InsertText,text,MUIV_TextEditor_InsertText_Bottom);
}
break;
}
}
socks->Timehack = time(NULL);
return;
}
void __asm EndChat(REG(a2) APTR obj)
{
int i;
ULONG winuin, total, sess_count;
struct ChatSession *session;
struct Contact *user;
struct RemoteChatObj *RCObj;
struct Sockets *socks, *primesocks;
HandleError(DBG_TCP_DBUG,"EndChat()");
get(obj,MUIA_UserData,&winuin);
if (!(user = GetContact(winuin))) return;
if (!(socks = GetSocketFmContact(user,SOCK_CHAT))) return;
if (socks->Closing) return;
if (!(primesocks = GetSocketFmPort(socks->ConnectPort))) {
DelSockets(socks->Socket);
return;
}
if (!socks->RCObj) {
HandleError(DBG_TCP_DBUG,"Got an empty socks->RCObj");
DelSockets(socks->Socket);
return;
}
RCObj = socks->RCObj;
socks->RCObj = NULL;
DelSockets(socks->Socket);
user->ChatListen = 0;
SaveChatText(user,primesocks->CWin,RCObj);
if (RCObj) {
DoMethod(primesocks->CWin->GP_ChatGroups,MUIM_Group_InitChange);
DoMethod(primesocks->CWin->GP_ChatGroups,OM_REMMEMBER,RCObj->GP_RemoteObj);
MUI_DisposeObject(RCObj->GP_RemoteObj);
FreeVec(RCObj);
RCObj = NULL;
DoMethod(primesocks->CWin->GP_ChatGroups,MUIM_Group_ExitChange);
}
sess_count = CountChatPorts(primesocks);
if (sess_count == 0) {
set(primesocks->CWin->WI_ChatWin,MUIA_Window_Open,FALSE);
DoMethod(app->App,OM_REMMEMBER,primesocks->CWin->WI_ChatWin);
MUI_DisposeObject(primesocks->CWin->WI_ChatWin);
FreeVec(primesocks->CWin);
primesocks->CWin = NULL;
get(app->LV_Sessions,MUIA_NList_Entries,&total);
if (total > 0) {
for(i = 0; i < total; i++) {
DoMethod(app->LV_Sessions,MUIM_NList_GetEntry,i,&session);
if (session) {
if (session->ChatListen == primesocks->Port) {
DoMethod(app->LV_Sessions,MUIM_NList_Remove,i);
break;
}
}
}
}
DelSockets(primesocks->Socket);
}
else UpdateChatSession(user,primesocks);
return;
}
void __asm ChatWinState(REG(a2) APTR obj)
{
BOOL *active;
char key[2];
ULONG uin;
struct Contact *user;
struct Sockets *primesocks;
get(obj,MUIA_UserData,&uin);
if (!(user = GetContact(uin))) return;
if (!(primesocks = GetSocketFmPort(user->ChatListen))) return;
key[1] = '\0';
get(primesocks->CWin->WI_ChatWin,MUIA_Window_Activate,&active);
if (active) key[0] = '\x03';
else key[0] = '\x04';
SendText(primesocks->Port,key,1);
return;
}
void UpdateChatSession(struct Contact *user, struct Sockets *primesocks)
{
BOOL flag = FALSE;
char *nick;
int i;
ULONG total;
struct ChatSession *session, Sess;
get(app->STR_Nick,MUIA_String_Contents,&nick);
strcpy(primesocks->CWin->Title,GetSessionNicks(primesocks));
set(primesocks->CWin->WI_ChatWin,MUIA_Window_Title,primesocks->CWin->Title);
get(app->LV_Sessions,MUIA_NList_Entries,&total);
if (total > 0) {
for(i = 0; i < total; i++) {
DoMethod(app->LV_Sessions,MUIM_NList_GetEntry,i,&session);
if (session) {
if (session->ChatListen == primesocks->Port) {
strcpy(session->Session,primesocks->CWin->Title);
flag = TRUE;
break;
}
}
}
}
if (!flag) {
Sess.ChatListen = primesocks->Port;
strcpy(Sess.Session,primesocks->CWin->Title);
DoMethod(app->LV_Sessions,MUIM_NList_InsertSingle,&Sess,MUIV_NList_Insert_Sorted);
}
return;
}
struct ChatSession *GetChatSessionPort(UWORD port)
{
int i;
ULONG total;
struct ChatSession *session;
get(app->LV_Sessions,MUIA_NList_Entries,&total);
if (total > 0) {
for(i = 0; i < total; i++) {
DoMethod(app->LV_Sessions,MUIM_NList_GetEntry,i,&session);
if (session) if (session->ChatListen == port) return(session);
}
}
return(NULL);
}
ULONG CountChatPorts(struct Sockets *primesocks)
{
int i;
ULONG total, count = 0;
struct Sockets *socks;
HandleError(DBG_TCP_DBUG,"CountChatPorts(%d)",primesocks->Port);
get(app->LV_SockList,MUIA_NList_Entries,&total);
for(i = 0; i < total; i++) {
DoMethod(app->LV_SockList,MUIM_NList_GetEntry,i,&socks);
if (socks) {
if (socks->ConnectPort == primesocks->Port && socks != primesocks) {
count++;
HandleError(DBG_TCP_DBUG,"Socket %d has ConnectPort %d",socks->Socket,socks->ConnectPort);
}
}
}
HandleError(DBG_TCP_DBUG,"CountChatPorts() = %ld",count);
return(count);
}
void SaveChatText(struct Contact *user, struct ChatWin *CWin, struct RemoteChatObj *RCObj)
{
char uinlog[MAXNAMLEN], *rchat, *lchat;
ULONG uin;
struct AsyncFile *logfh;
rchat = (char *)DoMethod(RCObj->TE_ChatRemote,MUIM_TextEditor_ExportText);
lchat = (char *)DoMethod(CWin->TE_ChatLocal,MUIM_TextEditor_ExportText);
if (!rchat) rchat = LINE;
if (!lchat) lchat = LINE;
if (!strlen(rchat) && !strlen(lchat)) return;
/*
MUI hits enforcer/cyberguard/muforce when the next line is executed. I see this as an MUI bug, not STRICQ.
*/
if (MUI_Request(app->App,CWin->WI_ChatWin,0,NULL,"Save|Discard","Save Chat Contents?")) {
get(app->STR_ICQUIN,MUIA_String_Integer,&uin);
sprintf(uinlog,"%sUsers/%ld/Logs/%ld",currentdir,uin,user->UIN);
if (logfh = OpenAsync(uinlog,MODE_APPEND,AsyncBuf)) {
// for(c = rchat; *c; c++) if (*c == '\n') *c = ' ';
WriteLineAsync(logfh,"Chat R: ");
WriteLineAsync(logfh,rchat);
WriteLineAsync(logfh,"\n\n");
set(RCObj->TE_ChatRemote,MUIA_TextEditor_Contents,NULL);
if (strlen(rchat)) FreeVec(rchat);
// for(c = lchat; *c; c++) if (*c == '\n') *c = ' ';
WriteLineAsync(logfh,"Chat S: ");
WriteLineAsync(logfh,lchat);
WriteLineAsync(logfh,"\n\n");
set(CWin->TE_ChatLocal,MUIA_TextEditor_Contents,NULL);
if (strlen(lchat)) FreeVec(lchat);
CloseAsync(logfh);
SetComment(uinlog,GetNick(user->UIN));
}
}
return;
}
void __asm EndAllChat(REG(a2) APTR obj)
{
int i;
ULONG winuin, total;
struct ChatSession *session;
struct Contact *user;
struct Sockets *socks, *primesocks;
get(obj,MUIA_UserData,&winuin);
if (!(user = GetContact(winuin))) return;
if (!(primesocks = GetSocketFmPort(user->ChatListen))) return;
get(app->LV_SockList,MUIA_NList_Entries,&total);
for(i = 0; i < total; i++) {
DoMethod(app->LV_SockList,MUIM_NList_GetEntry,i,&socks);
if (socks) if (socks->ConnectPort == primesocks->Port && socks != primesocks) socks->Closing = TRUE;
}
if (!MUI_Request(app->App,primesocks->CWin->WI_ChatWin,0,NULL,"Yes|No","Exit Chat. Are you sure?")) {
for(i = 0; i < total; i++) {
DoMethod(app->LV_SockList,MUIM_NList_GetEntry,i,&socks);
if (socks) if (socks->ConnectPort == primesocks->Port && socks != primesocks) socks->Closing = FALSE;
}
return;
}
for(i = 0; i < total; i++) {
DoMethod(app->LV_SockList,MUIM_NList_GetEntry,i,&socks);
if (socks) {
if (socks->ConnectPort == primesocks->Port && socks != primesocks) {
user = GetContact(socks->UIN);
user->ChatListen = 0;
HandleError(DBG_TCP_DBUG,"Shutting down %s's chat socket %d",user->Nick,socks->Socket);
if (socks->RCObj) {
SaveChatText(user,primesocks->CWin,socks->RCObj);
DoMethod(primesocks->CWin->GP_ChatGroups,MUIM_Group_InitChange);
DoMethod(primesocks->CWin->GP_ChatGroups,OM_REMMEMBER,socks->RCObj->GP_RemoteObj);
MUI_DisposeObject(socks->RCObj->GP_RemoteObj);
FreeVec(socks->RCObj);
socks->RCObj = NULL;
DoMethod(primesocks->CWin->GP_ChatGroups,MUIM_Group_ExitChange);
}
send(socks->Socket,"\x0B",1,0);
DelSockets(socks->Socket);
}
}
}
set(primesocks->CWin->WI_ChatWin,MUIA_Window_Open,FALSE);
DoMethod(app->App,OM_REMMEMBER,primesocks->CWin->WI_ChatWin);
MUI_DisposeObject(primesocks->CWin->WI_ChatWin);
FreeVec(primesocks->CWin);
primesocks->CWin = NULL;
get(app->LV_Sessions,MUIA_NList_Entries,&total);
if (total > 0) {
for(i = 0; i < total; i++) {
DoMethod(app->LV_Sessions,MUIM_NList_GetEntry,i,&session);
if (session) {
if (session->ChatListen == primesocks->Port) {
DoMethod(app->LV_Sessions,MUIM_NList_Remove,i);
break;
}
}
}
}
DelSockets(primesocks->Socket);
return;
}
void __asm SetBIU(REG(a2) APTR obj)
{
BOOL *bold, *italic, *underline;
char buf[16];
ULONG uin;
UWORD len;
struct Contact *user;
struct Sockets *primesocks;
struct TCP_ChatCmdStyle Style;
get(obj,MUIA_UserData,&uin);
user = GetContact(uin);
primesocks = GetSocketFmPort(user->ChatListen);
get(primesocks->CWin->TE_ChatLocal,MUIA_TextEditor_StyleBold,&bold);
get(primesocks->CWin->TE_ChatLocal,MUIA_TextEditor_StyleItalic,&italic);
get(primesocks->CWin->TE_ChatLocal,MUIA_TextEditor_StyleUnderline,&underline);
Style.Bold = (bold?TRUE:FALSE);
Style.Italic = (italic?TRUE:FALSE);
Style.Underline = (underline?TRUE:FALSE);
len = TCP_CreateChatCmd(TCP_CHAT_CMD_STYLE,&Style,buf);
SendText(primesocks->Port,buf,len);
return;
}
void SendText(UWORD port, char *text, UWORD len)
{
int i;
ULONG total;
struct Sockets *socks;
get(app->LV_SockList,MUIA_NList_Entries,&total);
for(i = 0; i < total; i++) {
DoMethod(app->LV_SockList,MUIM_NList_GetEntry,i,&socks);
if (socks) {
if (socks->ConnectPort == port && socks->Dir != TCP_DIR_LISTEN) {
send(socks->Socket,text,len,0);
socks->Timehack = time(NULL);
}
}
}
return;
}
void __asm SetLocalFColor(REG(a2) APTR obj)
{
char buf[16];
LONG entry;
ULONG uin;
UWORD len;
struct Contact *user;
struct Sockets *primesocks;
struct TCP_ChatColor Color;
get(obj,MUIA_NList_EntryClick,&entry);
if (entry < 0 || entry >= NUM_CHAT_COLORS) return;
get(obj,MUIA_NList_PrivateData,&uin);
user = GetContact(uin);
primesocks = GetSocketFmPort(user->ChatListen);
set(primesocks->CWin->TE_ChatLocal,MUIA_TextEditor_Pen,entry+1);
Color.Red = ChatColors[entry][0];
Color.Green = ChatColors[entry][1];
Color.Blue = ChatColors[entry][2];
len = TCP_CreateChatCmd(TCP_CHAT_CMD_FCOLOR,&Color,buf);
SendText(primesocks->Port,buf,len);
return;
}