2009-05-08 13:28:41 +00:00
|
|
|
|
/*
|
|
|
|
|
* OpenClonk, http://www.openclonk.org
|
|
|
|
|
*
|
2009-06-05 13:41:20 +00:00
|
|
|
|
* Copyright (c) 2007 Sven Eberhardt
|
|
|
|
|
* Copyright (c) 2007-2008 Matthes Bender
|
|
|
|
|
* Copyright (c) 2007 Peter Wortmann
|
|
|
|
|
* Copyright (c) 2007 Günther Brammer
|
2009-05-08 13:28:41 +00:00
|
|
|
|
* Copyright (c) 2007-2009, RedWolf Design GmbH, http://www.clonk.de
|
|
|
|
|
*
|
|
|
|
|
* Portions might be copyrighted by other authors who have contributed
|
|
|
|
|
* to OpenClonk.
|
|
|
|
|
*
|
|
|
|
|
* Permission to use, copy, modify, and/or distribute this software for any
|
|
|
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
|
|
|
* copyright notice and this permission notice appear in all copies.
|
|
|
|
|
* See isc_license.txt for full license and disclaimer.
|
|
|
|
|
*
|
|
|
|
|
* "Clonk" is a registered trademark of Matthes Bender.
|
|
|
|
|
* See clonk_trademark_license.txt for full license.
|
|
|
|
|
*/
|
|
|
|
|
// IRC client dialog
|
|
|
|
|
|
2009-11-25 18:38:54 +00:00
|
|
|
|
#include <utility>
|
|
|
|
|
|
2009-05-08 13:28:41 +00:00
|
|
|
|
#include "C4Include.h"
|
|
|
|
|
#include "C4ChatDlg.h"
|
2009-06-05 18:00:23 +00:00
|
|
|
|
|
2009-05-08 13:28:41 +00:00
|
|
|
|
#include "C4InputValidation.h"
|
|
|
|
|
#include "C4Network2IRC.h"
|
2009-06-05 18:00:23 +00:00
|
|
|
|
#include "C4MessageInput.h"
|
2010-06-27 00:42:48 +00:00
|
|
|
|
#include "C4GraphicsResource.h"
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
2009-06-28 20:53:32 +00:00
|
|
|
|
void ConvWindowsToUTF8(StdStrBuf &sText)
|
2009-05-08 13:28:41 +00:00
|
|
|
|
{
|
2009-06-28 20:53:32 +00:00
|
|
|
|
// work around (German) legacy clients using windows-1252
|
|
|
|
|
sText.Replace("<EFBFBD>", "\xc3\x84");
|
|
|
|
|
sText.Replace("<EFBFBD>", "\xc3\x96");
|
|
|
|
|
sText.Replace("<EFBFBD>", "\xc3\x9c");
|
|
|
|
|
sText.Replace("<EFBFBD>", "\xc3\xa4");
|
|
|
|
|
sText.Replace("<EFBFBD>", "\xc3\xb6");
|
|
|
|
|
sText.Replace("<EFBFBD>", "\xc3\xbc");
|
|
|
|
|
sText.Replace("<EFBFBD>", "\xc3\x9f");
|
2009-05-08 13:28:41 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* C4ChatControl::ChatSheet::NickItem */
|
|
|
|
|
|
|
|
|
|
C4ChatControl::ChatSheet::NickItem::NickItem(class C4Network2IRCUser *pByUser) : pStatusIcon(NULL), pNameLabel(NULL), fFlaggedExisting(false), iStatus(0)
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
// create elements - will be positioned when resized
|
|
|
|
|
C4Rect rcDefault(0,0,10,10);
|
|
|
|
|
AddElement(pStatusIcon = new C4GUI::Icon(rcDefault, C4GUI::Ico_None));
|
|
|
|
|
AddElement(pNameLabel = new C4GUI::Label("", rcDefault, ALeft, C4GUI_CaptionFontClr, NULL, false, false, false));
|
|
|
|
|
// set height (pos and width set when added to the list)
|
2010-06-27 00:42:48 +00:00
|
|
|
|
CStdFont *pUseFont = &::GraphicsResource.TextFont;
|
2009-05-08 13:28:41 +00:00
|
|
|
|
rcBounds.Set(0,0, 100,pUseFont->GetLineHeight());
|
|
|
|
|
// initial update
|
|
|
|
|
Update(pByUser);
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
|
|
void C4ChatControl::ChatSheet::NickItem::UpdateOwnPos()
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
typedef C4GUI::Window ParentClass;
|
|
|
|
|
ParentClass::UpdateOwnPos();
|
|
|
|
|
// reposition elements
|
|
|
|
|
if (pStatusIcon && pNameLabel)
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
C4GUI::ComponentAligner caMain(GetContainedClientRect(), 1,0);
|
|
|
|
|
pStatusIcon->SetBounds(caMain.GetFromLeft(caMain.GetInnerHeight()));
|
|
|
|
|
pNameLabel->SetBounds(caMain.GetAll());
|
|
|
|
|
}
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
|
|
void C4ChatControl::ChatSheet::NickItem::Update(class C4Network2IRCUser *pByUser)
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
// set status icon
|
|
|
|
|
const char *szPrefix = pByUser->getPrefix();
|
|
|
|
|
if (!szPrefix) szPrefix = "";
|
|
|
|
|
C4GUI::Icons eStatusIcon;
|
|
|
|
|
switch (*szPrefix)
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
|
|
|
|
case '!': eStatusIcon = C4GUI::Ico_Rank1; iStatus = 4; break;
|
|
|
|
|
case '@': eStatusIcon = C4GUI::Ico_Rank2; iStatus = 3; break;
|
|
|
|
|
case '%': eStatusIcon = C4GUI::Ico_Rank3; iStatus = 2; break;
|
|
|
|
|
case '+': eStatusIcon = C4GUI::Ico_AddPlr; iStatus = 1; break;
|
|
|
|
|
case '\0': eStatusIcon = C4GUI::Ico_Player; iStatus = 0; break;
|
|
|
|
|
default: eStatusIcon = C4GUI::Ico_Player; iStatus = 0; break;
|
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
pStatusIcon->SetIcon(eStatusIcon);
|
|
|
|
|
// set name
|
|
|
|
|
pNameLabel->SetText(pByUser->getName());
|
|
|
|
|
// tooltip is status+name
|
|
|
|
|
SetToolTip(FormatString("%s%s", szPrefix, pByUser->getName()).getData());
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
|
|
int32_t C4ChatControl::ChatSheet::NickItem::SortFunc(const C4GUI::Element *pEl1, const C4GUI::Element *pEl2, void *)
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
const NickItem *pNickItem1 = static_cast<const NickItem *>(pEl1);
|
|
|
|
|
const NickItem *pNickItem2 = static_cast<const NickItem *>(pEl2);
|
|
|
|
|
int32_t s1 = pNickItem1->GetStatus(), s2 = pNickItem2->GetStatus();
|
|
|
|
|
if (s1 != s2) return s1 - s2;
|
|
|
|
|
return stricmp(pNickItem2->GetNick(), pNickItem1->GetNick());
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* C4ChatControl::ChatSheet */
|
|
|
|
|
|
|
|
|
|
C4ChatControl::ChatSheet::ChatSheet(C4ChatControl *pChatControl, const char *szTitle, const char *szIdent, SheetType eType)
|
2010-03-28 18:58:01 +00:00
|
|
|
|
: C4GUI::Tabular::Sheet(szTitle, C4Rect(0,0,10,10), C4GUI::Ico_None, true, false), pChatControl(pChatControl), pNickList(NULL), pInputLbl(NULL), iBackBufferIndex(-1), eType(eType), fHasUnread(false)
|
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
if (szIdent) sIdent.Copy(szIdent);
|
|
|
|
|
// create elements - positioned later
|
|
|
|
|
C4Rect rcDefault(0,0,10,10);
|
|
|
|
|
pChatBox = new C4GUI::TextWindow(rcDefault);
|
|
|
|
|
//pChatBox->SetToolTip(LoadResStr("IDS_DLGTIP_CHATWIN")); tooltip doesn't really help, only makes things un<75>bersichtlich
|
|
|
|
|
pChatBox->SetDecoration(false, false, NULL, false);
|
|
|
|
|
AddElement(pChatBox);
|
|
|
|
|
if (eType == CS_Channel)
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
pNickList = new C4GUI::ListBox(rcDefault);
|
|
|
|
|
pNickList->SetDecoration(false, NULL, true, false);
|
|
|
|
|
pNickList->SetSelectionDblClickFn(new C4GUI::CallbackHandler<C4ChatControl::ChatSheet>(this, &C4ChatControl::ChatSheet::OnNickDblClick));
|
|
|
|
|
AddElement(pNickList);
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
if (eType != CS_Server)
|
2010-06-27 00:42:48 +00:00
|
|
|
|
pInputLbl = new C4GUI::WoodenLabel(LoadResStr("IDS_DLG_CHAT"), rcDefault, C4GUI_CaptionFontClr, &::GraphicsResource.TextFont);
|
2009-05-08 13:28:41 +00:00
|
|
|
|
pInputEdit = new C4GUI::CallbackEdit<C4ChatControl::ChatSheet>(rcDefault, this, &C4ChatControl::ChatSheet::OnChatInput);
|
|
|
|
|
pInputEdit->SetToolTip(LoadResStr("IDS_DLGTIP_CHAT"));
|
|
|
|
|
if (pInputLbl)
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
pInputLbl->SetToolTip(LoadResStr("IDS_DLGTIP_CHAT"));
|
|
|
|
|
pInputLbl->SetClickFocusControl(pInputEdit);
|
|
|
|
|
AddElement(pInputLbl);
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
AddElement(pInputEdit);
|
|
|
|
|
// key bindings
|
|
|
|
|
pKeyHistoryUp = new C4KeyBinding(C4KeyCodeEx(K_UP ), "ChatHistoryUp" , KEYSCOPE_Gui, new C4GUI::DlgKeyCBEx<C4ChatControl::ChatSheet, bool>(*this, true , &C4ChatControl::ChatSheet::KeyHistoryUpDown), C4CustomKey::PRIO_CtrlOverride);
|
|
|
|
|
pKeyHistoryDown= new C4KeyBinding(C4KeyCodeEx(K_DOWN), "ChatHistoryDown", KEYSCOPE_Gui, new C4GUI::DlgKeyCBEx<C4ChatControl::ChatSheet, bool>(*this, false, &C4ChatControl::ChatSheet::KeyHistoryUpDown), C4CustomKey::PRIO_CtrlOverride);
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
|
|
C4ChatControl::ChatSheet::~ChatSheet()
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
delete pKeyHistoryUp;
|
|
|
|
|
delete pKeyHistoryDown;
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
|
|
void C4ChatControl::ChatSheet::UpdateSize()
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
// parent update
|
|
|
|
|
typedef C4GUI::Window ParentClass;
|
|
|
|
|
ParentClass::UpdateSize();
|
|
|
|
|
// position child elements
|
|
|
|
|
C4GUI::ComponentAligner caMain(GetContainedClientRect(), 0,0);
|
|
|
|
|
C4GUI::ComponentAligner caChat(caMain.GetFromBottom(C4GUI::Edit::GetDefaultEditHeight()), 0,0);
|
|
|
|
|
if (pNickList) pNickList->SetBounds(caMain.GetFromRight(Max<int32_t>(caMain.GetInnerWidth()/5, 100)));
|
|
|
|
|
pChatBox->SetBounds(caMain.GetAll());
|
|
|
|
|
if (pInputLbl) pInputLbl->SetBounds(caChat.GetFromLeft(40));
|
|
|
|
|
pInputEdit->SetBounds(caChat.GetAll());
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
|
|
void C4ChatControl::ChatSheet::OnShown(bool fByUser)
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
ResetUnread();
|
|
|
|
|
if (fByUser)
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
Update(true);
|
|
|
|
|
pChatControl->UpdateTitle();
|
|
|
|
|
}
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
|
|
C4GUI::Edit::InputResult C4ChatControl::ChatSheet::OnChatInput(C4GUI::Edit *edt, bool fPasting, bool fPastingMore)
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
C4GUI::Edit::InputResult eResult = C4GUI::Edit::IR_None;
|
|
|
|
|
// get edit text
|
|
|
|
|
const char *szInputText = pInputEdit->GetText();
|
|
|
|
|
// no input?
|
|
|
|
|
if (!szInputText || !*szInputText)
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
// do some error sound then
|
|
|
|
|
DoError(NULL);
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
else
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
// remember in history
|
2009-06-05 15:18:45 +00:00
|
|
|
|
::MessageInput.StoreBackBuffer(szInputText);
|
2009-05-08 13:28:41 +00:00
|
|
|
|
// forward to chat control for processing
|
|
|
|
|
if (!pChatControl->ProcessInput(szInputText, this)) eResult = C4GUI::Edit::IR_Abort;
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
// clear edit field after text has been processed
|
|
|
|
|
pInputEdit->SelectAll(); pInputEdit->DeleteSelection();
|
|
|
|
|
// reset backbuffer-index of chat history
|
|
|
|
|
iBackBufferIndex = -1;
|
|
|
|
|
// OK, on we go
|
|
|
|
|
return eResult;
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
|
|
bool C4ChatControl::ChatSheet::KeyHistoryUpDown(bool fUp)
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
// chat input only
|
|
|
|
|
if (!IsFocused(pInputEdit)) return false;
|
|
|
|
|
pInputEdit->SelectAll(); pInputEdit->DeleteSelection();
|
2009-06-05 15:18:45 +00:00
|
|
|
|
const char *szPrevInput = ::MessageInput.GetBackBuffer(fUp ? (++iBackBufferIndex) : (--iBackBufferIndex));
|
2009-05-08 13:28:41 +00:00
|
|
|
|
if (!szPrevInput || !*szPrevInput)
|
|
|
|
|
iBackBufferIndex = -1;
|
|
|
|
|
else
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
pInputEdit->InsertText(szPrevInput, true);
|
|
|
|
|
pInputEdit->SelectAll();
|
|
|
|
|
}
|
2010-03-28 18:58:01 +00:00
|
|
|
|
return true;
|
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
|
|
void C4ChatControl::ChatSheet::OnNickDblClick(class C4GUI::Element *pEl)
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
if (!pEl) return;
|
|
|
|
|
NickItem *pNickItem = static_cast<NickItem *>(pEl);
|
|
|
|
|
pChatControl->OpenQuery(pNickItem->GetNick(), true, NULL);
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
|
|
void C4ChatControl::ChatSheet::AddTextLine(const char *szText, uint32_t dwClr)
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
// strip stuff that would confuse Clonk
|
|
|
|
|
StdStrBuf sText; sText.Copy(szText);
|
|
|
|
|
for (char c='\x01'; c<' '; ++c)
|
|
|
|
|
sText.ReplaceChar(c, ' ');
|
2009-06-28 20:53:32 +00:00
|
|
|
|
// convert incoming Windows-1252
|
|
|
|
|
ConvWindowsToUTF8(sText);
|
2009-05-08 13:28:41 +00:00
|
|
|
|
// add text line to chat box
|
2010-06-27 00:42:48 +00:00
|
|
|
|
CStdFont *pUseFont = &::GraphicsResource.TextFont;
|
2009-05-08 13:28:41 +00:00
|
|
|
|
pChatBox->AddTextLine(sText.getData(), pUseFont, dwClr, true, false);
|
|
|
|
|
pChatBox->ScrollToBottom();
|
|
|
|
|
// sheet now has unread messages if not selected
|
|
|
|
|
if (!fHasUnread && !IsActiveSheet())
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
fHasUnread = true;
|
|
|
|
|
SetCaptionColor(C4GUI_Caption2FontClr);
|
|
|
|
|
}
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
|
|
void C4ChatControl::ChatSheet::ResetUnread()
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
// mark messages as read
|
|
|
|
|
if (fHasUnread)
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
fHasUnread = false;
|
|
|
|
|
SetCaptionColor();
|
|
|
|
|
}
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
|
|
void C4ChatControl::ChatSheet::DoError(const char *szError)
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
if (szError)
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
AddTextLine(szError, C4GUI_ErrorFontClr);
|
|
|
|
|
}
|
2010-03-28 18:58:01 +00:00
|
|
|
|
C4GUI::GUISound("Error");
|
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
|
|
void C4ChatControl::ChatSheet::Update(bool fLock)
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
// lock IRC client data if desired
|
|
|
|
|
if (fLock)
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
CStdLock Lock(pChatControl->getIRCClient()->getCSec());
|
|
|
|
|
Update(false);
|
|
|
|
|
return;
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
// only channels need updates
|
|
|
|
|
if (eType == CS_Channel)
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
C4Network2IRCChannel *pIRCChan = pChatControl->getIRCClient()->getChannel(GetIdent());
|
|
|
|
|
if (pIRCChan)
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
// update user list (if not locked, becuase it's being received)
|
|
|
|
|
if (!pIRCChan->isUsersLocked()) UpdateUsers(pIRCChan->getUsers());
|
|
|
|
|
// update topic
|
|
|
|
|
const char *szTopic = pIRCChan->getTopic();
|
|
|
|
|
sChatTitle.Format("%s%s%s", sIdent.getData(), szTopic ? ": " : "", szTopic ? szTopic : "");
|
2009-06-28 20:53:32 +00:00
|
|
|
|
ConvWindowsToUTF8(sChatTitle);
|
2009-05-08 13:28:41 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
|
|
void C4ChatControl::ChatSheet::UpdateUsers(C4Network2IRCUser *pUsers)
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
NickItem *pNickItem, *pNextNickItem;
|
|
|
|
|
// update existing users
|
|
|
|
|
for (; pUsers; pUsers = pUsers->getNext())
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2010-01-25 04:00:59 +00:00
|
|
|
|
if ((pNickItem = GetNickItem(pUsers->getName())))
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
pNickItem->Update(pUsers);
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
else
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
// new user!
|
|
|
|
|
pNickItem = new NickItem(pUsers);
|
|
|
|
|
pNickList->AddElement(pNickItem);
|
|
|
|
|
}
|
2010-03-28 18:58:01 +00:00
|
|
|
|
pNickItem->SetFlaggedExisting(true);
|
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
// remove left users
|
|
|
|
|
pNextNickItem = GetFirstNickItem();
|
2010-01-25 04:00:59 +00:00
|
|
|
|
while ((pNickItem = pNextNickItem))
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
pNextNickItem = GetNextNickItem(pNickItem);
|
|
|
|
|
if (!pNickItem->IsFlaggedExisting())
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
// this user left
|
|
|
|
|
delete pNickItem;
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
else
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
// user didn't leave; reset flag for next check
|
|
|
|
|
pNickItem->SetFlaggedExisting(false);
|
|
|
|
|
}
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
// sort the rest
|
|
|
|
|
pNickList->SortElements(&NickItem::SortFunc, NULL);
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
|
|
void C4ChatControl::ChatSheet::UserClose()
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
typedef C4GUI::Tabular::Sheet ParentClass;
|
|
|
|
|
switch (eType)
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
|
|
|
|
case CS_Server:
|
|
|
|
|
// closing server window? Always forward to control
|
|
|
|
|
pChatControl->UserQueryQuit();
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case CS_Channel:
|
|
|
|
|
// channel: Send part. Close done by server.
|
|
|
|
|
pChatControl->getIRCClient()->Part(sIdent.getData());
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case CS_Query:
|
|
|
|
|
// query: Always allow simple close
|
|
|
|
|
ParentClass::UserClose();
|
|
|
|
|
break;
|
2009-05-08 13:28:41 +00:00
|
|
|
|
}
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
|
|
C4ChatControl::ChatSheet::NickItem *C4ChatControl::ChatSheet::GetNickItem(const char *szByNick)
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
// find by name
|
|
|
|
|
for (NickItem *pNickItem = GetFirstNickItem(); pNickItem; pNickItem = GetNextNickItem(pNickItem))
|
|
|
|
|
if (SEqualNoCase(pNickItem->GetNick(), szByNick))
|
|
|
|
|
return pNickItem;
|
|
|
|
|
// not found
|
|
|
|
|
return NULL;
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* C4ChatControl */
|
|
|
|
|
|
|
|
|
|
C4ChatControl::C4ChatControl(C4Network2IRCClient *pnIRCClient) : C4GUI::Window(), pTitleChangeBC(NULL), pIRCClient(pnIRCClient), fInitialMessagesReceived(false)
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
// create elements - positioned later
|
|
|
|
|
C4Rect rcDefault(0,0,10,10);
|
|
|
|
|
// main tabular tabs between chat components (login and channels)
|
|
|
|
|
pTabMain = new C4GUI::Tabular(rcDefault, C4GUI::Tabular::tbNone);
|
|
|
|
|
pTabMain->SetDrawDecoration(false);
|
|
|
|
|
pTabMain->SetSheetMargin(0);
|
|
|
|
|
AddElement(pTabMain);
|
|
|
|
|
C4GUI::Tabular::Sheet *pSheetLogin = pTabMain->AddSheet(NULL);
|
|
|
|
|
C4GUI::Tabular::Sheet *pSheetChats = pTabMain->AddSheet(NULL);
|
|
|
|
|
// login sheet
|
2010-06-27 00:42:48 +00:00
|
|
|
|
CStdFont *pUseFont = &::GraphicsResource.TextFont;
|
2009-05-08 13:28:41 +00:00
|
|
|
|
pSheetLogin->AddElement(pLblLoginNick = new C4GUI::Label(LoadResStr("IDS_CTL_NICK"), rcDefault, ALeft, C4GUI_CaptionFontClr, pUseFont, false, true));
|
|
|
|
|
pSheetLogin->AddElement(pEdtLoginNick = new C4GUI::CallbackEdit<C4ChatControl>(rcDefault, this, &C4ChatControl::OnLoginDataEnter));
|
|
|
|
|
pSheetLogin->AddElement(pLblLoginPass = new C4GUI::Label(LoadResStr("IDS_CTL_PASSWORDOPTIONAL"), rcDefault, ALeft, C4GUI_CaptionFontClr, pUseFont, false, true));
|
|
|
|
|
pSheetLogin->AddElement(pEdtLoginPass = new C4GUI::CallbackEdit<C4ChatControl>(rcDefault, this, &C4ChatControl::OnLoginDataEnter));
|
|
|
|
|
pEdtLoginPass->SetPasswordMask('*');
|
|
|
|
|
pSheetLogin->AddElement(pLblLoginRealName = new C4GUI::Label(LoadResStr("IDS_CTL_REALNAME"), rcDefault, ALeft, C4GUI_CaptionFontClr, pUseFont, false, true));
|
|
|
|
|
pSheetLogin->AddElement(pEdtLoginRealName = new C4GUI::CallbackEdit<C4ChatControl>(rcDefault, this, &C4ChatControl::OnLoginDataEnter));
|
|
|
|
|
pSheetLogin->AddElement(pLblLoginChannel = new C4GUI::Label(LoadResStr("IDS_CTL_CHANNEL"), rcDefault, ALeft, C4GUI_CaptionFontClr, pUseFont, false, true));
|
|
|
|
|
pSheetLogin->AddElement(pEdtLoginChannel = new C4GUI::CallbackEdit<C4ChatControl>(rcDefault, this, &C4ChatControl::OnLoginDataEnter));
|
|
|
|
|
pSheetLogin->AddElement(pBtnLogin = new C4GUI::CallbackButtonEx<C4ChatControl>(LoadResStr("IDS_BTN_CONNECT"), rcDefault, this, &C4ChatControl::OnConnectBtn));
|
|
|
|
|
// channel/query tabular
|
|
|
|
|
pTabChats = new C4GUI::Tabular(rcDefault, C4GUI::Tabular::tbTop);
|
|
|
|
|
pTabChats->SetSheetMargin(0);
|
|
|
|
|
pSheetChats->AddElement(pTabChats);
|
|
|
|
|
// initial connection values
|
|
|
|
|
const char *szNick = Config.IRC.Nick, *szRealName = Config.IRC.RealName;
|
|
|
|
|
StdStrBuf sNick, sRealName;
|
|
|
|
|
if (!*szNick) szNick = Config.Network.Nick.getData();
|
|
|
|
|
pEdtLoginNick->SetText(szNick, false);
|
|
|
|
|
pEdtLoginRealName->SetText(szRealName, false);
|
|
|
|
|
pEdtLoginChannel->SetText(Config.IRC.Channel, false);
|
|
|
|
|
// initial sheets
|
|
|
|
|
ClearChatSheets();
|
2010-03-27 16:05:02 +00:00
|
|
|
|
// set IRC event callback
|
|
|
|
|
Application.InteractiveThread.SetCallback(Ev_IRC_Message, this);
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
|
|
C4ChatControl::~C4ChatControl()
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2010-03-27 16:05:02 +00:00
|
|
|
|
Application.InteractiveThread.ClearCallback(Ev_IRC_Message, this);
|
2009-05-08 13:28:41 +00:00
|
|
|
|
delete pTitleChangeBC;
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
|
|
void C4ChatControl::SetTitleChangeCB(C4GUI::BaseInputCallback *pNewCB)
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
delete pTitleChangeBC;
|
|
|
|
|
pTitleChangeBC = pNewCB;
|
|
|
|
|
// initial title
|
|
|
|
|
if (pTitleChangeBC) pTitleChangeBC->OnOK(sTitle);
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
|
|
void C4ChatControl::UpdateSize()
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
// parent update
|
|
|
|
|
typedef C4GUI::Window ParentClass;
|
|
|
|
|
ParentClass::UpdateSize();
|
|
|
|
|
// position child elements
|
|
|
|
|
pTabMain->SetBounds(GetContainedClientRect());
|
|
|
|
|
pTabChats->SetBounds(pTabChats->GetParent()->GetContainedClientRect());
|
|
|
|
|
C4GUI::Tabular::Sheet *pSheetLogin = pTabMain->GetSheet(0);
|
|
|
|
|
C4GUI::ComponentAligner caLoginSheet(pSheetLogin->GetContainedClientRect(), 0,0, false);
|
2010-06-27 00:42:48 +00:00
|
|
|
|
CStdFont *pUseFont = &::GraphicsResource.TextFont;
|
2009-05-08 13:28:41 +00:00
|
|
|
|
int32_t iIndent1 = C4GUI_DefDlgSmallIndent/2, iIndent2 = C4GUI_DefDlgIndent/2;
|
|
|
|
|
int32_t iLoginHgt = pUseFont->GetLineHeight() * 8 + iIndent1*10 + iIndent2*10 + C4GUI_ButtonHgt + 20;
|
|
|
|
|
int32_t iLoginWdt = iLoginHgt*2/3;
|
|
|
|
|
C4GUI::ComponentAligner caLogin(caLoginSheet.GetCentered(Min<int32_t>(iLoginWdt, caLoginSheet.GetInnerWidth()), Min<int32_t>(iLoginHgt, caLoginSheet.GetInnerHeight())), iIndent1, iIndent1);
|
|
|
|
|
pLblLoginNick->SetBounds(caLogin.GetFromTop(pUseFont->GetLineHeight()));
|
|
|
|
|
pEdtLoginNick->SetBounds(caLogin.GetFromTop(C4GUI::Edit::GetDefaultEditHeight()));
|
|
|
|
|
caLogin.ExpandTop(2*(iIndent1-iIndent2));
|
|
|
|
|
pLblLoginPass->SetBounds(caLogin.GetFromTop(pUseFont->GetLineHeight()));
|
|
|
|
|
pEdtLoginPass->SetBounds(caLogin.GetFromTop(C4GUI::Edit::GetDefaultEditHeight()));
|
|
|
|
|
caLogin.ExpandTop(2*(iIndent1-iIndent2));
|
|
|
|
|
pLblLoginRealName->SetBounds(caLogin.GetFromTop(pUseFont->GetLineHeight()));
|
|
|
|
|
pEdtLoginRealName->SetBounds(caLogin.GetFromTop(C4GUI::Edit::GetDefaultEditHeight()));
|
|
|
|
|
caLogin.ExpandTop(2*(iIndent1-iIndent2));
|
|
|
|
|
pLblLoginChannel->SetBounds(caLogin.GetFromTop(pUseFont->GetLineHeight()));
|
|
|
|
|
pEdtLoginChannel->SetBounds(caLogin.GetFromTop(C4GUI::Edit::GetDefaultEditHeight()));
|
|
|
|
|
caLogin.ExpandTop(2*(iIndent1-iIndent2));
|
|
|
|
|
pBtnLogin->SetBounds(caLogin.GetFromTop(C4GUI_ButtonHgt, C4GUI_DefButtonWdt));
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
|
|
void C4ChatControl::OnShown()
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
UpdateShownPage();
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
|
|
C4GUI::Control *C4ChatControl::GetDefaultControl()
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
// only return a default control if no control is selected to prevent deselection of other controls
|
|
|
|
|
if (GetDlg()->GetFocus()) return NULL;
|
|
|
|
|
ChatSheet *pActiveSheet = GetActiveChatSheet();
|
|
|
|
|
if (pActiveSheet) return pActiveSheet->GetInputEdit();
|
|
|
|
|
if (pBtnLogin->IsVisible()) return pBtnLogin;
|
|
|
|
|
return NULL;
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
|
|
C4ChatControl::ChatSheet *C4ChatControl::GetActiveChatSheet()
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
if (pTabChats->IsVisible())
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
C4GUI::Tabular::Sheet *pSheet = pTabChats->GetActiveSheet();
|
|
|
|
|
if (pSheet) return static_cast<ChatSheet *>(pSheet);
|
|
|
|
|
}
|
2010-03-28 18:58:01 +00:00
|
|
|
|
return NULL;
|
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
|
|
C4ChatControl::ChatSheet *C4ChatControl::GetSheetByIdent(const char *szIdent, C4ChatControl::ChatSheet::SheetType eType)
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
int32_t i=0; C4GUI::Tabular::Sheet *pSheet; const char *szCheckIdent;
|
2010-01-25 04:00:59 +00:00
|
|
|
|
while ((pSheet = pTabChats->GetSheet(i++)))
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
ChatSheet *pChatSheet = static_cast<ChatSheet *>(pSheet);
|
2010-01-25 04:00:59 +00:00
|
|
|
|
if ((szCheckIdent = pChatSheet->GetIdent()))
|
2009-05-08 13:28:41 +00:00
|
|
|
|
if (SEqualNoCase(szCheckIdent, szIdent))
|
|
|
|
|
if (eType == pChatSheet->GetSheetType())
|
|
|
|
|
return pChatSheet;
|
|
|
|
|
}
|
2010-03-28 18:58:01 +00:00
|
|
|
|
return NULL;
|
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
|
|
C4ChatControl::ChatSheet *C4ChatControl::GetSheetByTitle(const char *szTitle, C4ChatControl::ChatSheet::SheetType eType)
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
int32_t i=0; C4GUI::Tabular::Sheet *pSheet; const char *szCheckTitle;
|
2010-01-25 04:00:59 +00:00
|
|
|
|
while ((pSheet = pTabChats->GetSheet(i++)))
|
|
|
|
|
if ((szCheckTitle = pSheet->GetTitle()))
|
2009-05-08 13:28:41 +00:00
|
|
|
|
if (SEqualNoCase(szCheckTitle, szTitle))
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
ChatSheet *pChatSheet = static_cast<ChatSheet *>(pSheet);
|
|
|
|
|
if (eType == pChatSheet->GetSheetType())
|
|
|
|
|
return pChatSheet;
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
return NULL;
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
|
|
C4ChatControl::ChatSheet *C4ChatControl::GetServerSheet()
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
// server sheet is always the first
|
|
|
|
|
return static_cast<ChatSheet *>(pTabChats->GetSheet(0));
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
|
|
C4GUI::Edit::InputResult C4ChatControl::OnLoginDataEnter(C4GUI::Edit *edt, bool fPasting, bool fPastingMore)
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
// advance focus when user presses enter in one of the login edits
|
|
|
|
|
GetDlg()->AdvanceFocus(false);
|
|
|
|
|
// no more pasting
|
|
|
|
|
return C4GUI::Edit::IR_Abort;
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
|
|
void C4ChatControl::OnConnectBtn(C4GUI::Control *btn)
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
// check parameters
|
|
|
|
|
StdCopyStrBuf sNick(pEdtLoginNick->GetText());
|
|
|
|
|
StdCopyStrBuf sPass(pEdtLoginPass->GetText());
|
|
|
|
|
StdCopyStrBuf sRealName(pEdtLoginRealName->GetText());
|
|
|
|
|
StdCopyStrBuf sChannel (pEdtLoginChannel->GetText());
|
|
|
|
|
StdCopyStrBuf sServer(Config.IRC.Server);
|
|
|
|
|
if (C4InVal::ValidateString(sNick, C4InVal::VAL_IRCName))
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
GetScreen()->ShowErrorMessage(LoadResStr("IDS_ERR_INVALIDNICKNAME"));
|
|
|
|
|
GetDlg()->SetFocus(pEdtLoginNick, false);
|
|
|
|
|
return;
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
if (sPass.getLength() && C4InVal::ValidateString(sPass, C4InVal::VAL_IRCPass))
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
GetScreen()->ShowErrorMessage(LoadResStr("IDS_ERR_INVALIDPASSWORDMAX31CHARA"));
|
|
|
|
|
GetDlg()->SetFocus(pEdtLoginPass, false);
|
|
|
|
|
return;
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
if (sChannel.getLength() && C4InVal::ValidateString(sChannel, C4InVal::VAL_IRCChannel))
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
GetScreen()->ShowErrorMessage(LoadResStr("IDS_ERR_INVALIDCHANNELNAME"));
|
|
|
|
|
GetDlg()->SetFocus(pEdtLoginChannel, false);
|
|
|
|
|
return;
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
if (!sPass.getLength()) sPass.Clear();
|
|
|
|
|
if (!sChannel.getLength()) sChannel.Clear();
|
|
|
|
|
// store back config values
|
|
|
|
|
SCopy(sNick.getData(), Config.IRC.Nick, CFG_MaxString);
|
|
|
|
|
SCopy(sRealName.getData(), Config.IRC.RealName, CFG_MaxString);
|
|
|
|
|
SCopy(sChannel.getData(), Config.IRC.Channel, CFG_MaxString);
|
|
|
|
|
// show chat warning
|
|
|
|
|
StdStrBuf sWarnMsg;
|
|
|
|
|
sWarnMsg.Format(LoadResStr("IDS_MSG_YOUAREABOUTTOCONNECTTOAPU"), sServer.getData());
|
|
|
|
|
if (!GetScreen()->ShowMessageModal(sWarnMsg.getData(), LoadResStr("IDS_MSG_CHATDISCLAIMER"), C4GUI::MessageDialog::btnOKAbort, C4GUI::Ico_Notify, &Config.Startup.HideMsgIRCDangerous))
|
|
|
|
|
return;
|
2010-03-27 16:05:02 +00:00
|
|
|
|
// set up IRC callback
|
|
|
|
|
pIRCClient->SetNotify(&Application.InteractiveThread);
|
2009-05-08 13:28:41 +00:00
|
|
|
|
// initiate connection
|
|
|
|
|
if (!pIRCClient->Connect(sServer.getData(), sNick.getData(), sRealName.getData(), sPass.getData(), sChannel.getData()))
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
GetScreen()->ShowErrorMessage(FormatString(LoadResStr("IDS_ERR_IRCCONNECTIONFAILED"), pIRCClient->GetError()).getData());
|
|
|
|
|
return;
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2010-03-27 16:05:02 +00:00
|
|
|
|
// enable client execution
|
|
|
|
|
Application.InteractiveThread.AddProc(pIRCClient);
|
2009-05-08 13:28:41 +00:00
|
|
|
|
// reset chat sheets (close queries, etc.)
|
|
|
|
|
ClearChatSheets();
|
|
|
|
|
// connection message
|
|
|
|
|
ChatSheet *pServerSheet = GetServerSheet();
|
|
|
|
|
if (pServerSheet)
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
pServerSheet->SetChatTitle(sServer.getData());
|
|
|
|
|
pServerSheet->AddTextLine(FormatString(LoadResStr("IDS_NET_CONNECTING"), sServer.getData(), "").getData(), C4GUI_MessageFontClr);
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
// switch to server window
|
|
|
|
|
UpdateShownPage();
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
|
|
void C4ChatControl::UpdateShownPage()
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
if (pIRCClient->IsActive())
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
// connected to a server: Show chat window
|
|
|
|
|
pTabMain->SelectSheet(1, false);
|
|
|
|
|
Update();
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
else
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
// not connected: Login stuff
|
|
|
|
|
pTabMain->SelectSheet((int)0, false);
|
|
|
|
|
UpdateTitle();
|
|
|
|
|
}
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
|
|
bool C4ChatControl::IsServiceName(const char *szName)
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
// return true for some hardcoded list of service names
|
|
|
|
|
if (!szName) return false;
|
|
|
|
|
const char *szServiceNames [] = { "NickServ", "ChanServ", "MemoServ", "HelpServ", "Global", NULL }, *szServiceName;
|
|
|
|
|
int32_t i = 0;
|
2010-01-25 04:00:59 +00:00
|
|
|
|
while ((szServiceName = szServiceNames[i++]))
|
2009-05-08 13:28:41 +00:00
|
|
|
|
if (SEqualNoCase(szName, szServiceName))
|
|
|
|
|
return true;
|
|
|
|
|
return false;
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
|
|
void C4ChatControl::Update()
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
CStdLock Lock(pIRCClient->getCSec());
|
|
|
|
|
// update channels
|
|
|
|
|
for (C4Network2IRCChannel *pChan = pIRCClient->getFirstChannel(); pChan; pChan = pIRCClient->getNextChannel(pChan))
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
ChatSheet *pChanSheet = GetSheetByIdent(pChan->getName(), ChatSheet::CS_Channel);
|
|
|
|
|
if (!pChanSheet)
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
// new channel! Create sheet for it
|
|
|
|
|
pTabChats->AddCustomSheet(pChanSheet = new ChatSheet(this, pChan->getName(), pChan->getName(), ChatSheet::CS_Channel));
|
|
|
|
|
// and show immediately
|
|
|
|
|
pTabChats->SelectSheet(pChanSheet, false);
|
|
|
|
|
}
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
// remove parted channels
|
|
|
|
|
int32_t i=0; C4GUI::Tabular::Sheet *pSheet;
|
2010-01-25 04:00:59 +00:00
|
|
|
|
while ((pSheet = pTabChats->GetSheet(i++)))
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
C4Network2IRCChannel *pIRCChan;
|
|
|
|
|
ChatSheet *pChatSheet = static_cast<ChatSheet *>(pSheet);
|
|
|
|
|
if (pChatSheet->GetSheetType() == ChatSheet::CS_Channel)
|
|
|
|
|
if (!(pIRCChan = pIRCClient->getChannel(pChatSheet->GetTitle())))
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
delete pChatSheet;
|
|
|
|
|
--i;
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2010-03-27 16:05:02 +00:00
|
|
|
|
// retrieve messages: All messages in initial update; only unread in subsequent calls
|
|
|
|
|
C4Network2IRCMessage *pMsg;
|
2009-05-08 13:28:41 +00:00
|
|
|
|
if (fInitialMessagesReceived)
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
pMsg = pIRCClient->getUnreadMessageLog();
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
else
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
pMsg = pIRCClient->getMessageLog();
|
|
|
|
|
fInitialMessagesReceived = true;
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
// update messages
|
|
|
|
|
for (; pMsg; pMsg = pMsg->getNext())
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
// get target sheet to put message into
|
|
|
|
|
ChatSheet *pChatSheet; StdStrBuf sUser, sIdent;
|
|
|
|
|
bool fMsgToService = false;
|
|
|
|
|
if (pMsg->getType() == MSG_Server)
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
// server messages in server sheet
|
|
|
|
|
pChatSheet = GetServerSheet();
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
else
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
if (pMsg->getType() != MSG_Status) sUser.Copy(pMsg->getSource());
|
|
|
|
|
if (!sUser.SplitAtChar('!', &sIdent)) sIdent.Ref(sUser);
|
|
|
|
|
// message: Either channel or user message (or channel notify). Get correct sheet.
|
|
|
|
|
if (pMsg->isChannel())
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
// if no sheet is found, don't create - assume it's an outdated message with the cahnnel window already closed
|
|
|
|
|
pChatSheet = GetSheetByIdent(pMsg->getTarget(), ChatSheet::CS_Channel);
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
else if (IsServiceName(sUser.getData()))
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
// notices and messages by services always in server sheet
|
|
|
|
|
pChatSheet = GetServerSheet();
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
else if (pMsg->getType() == MSG_Notice)
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
// notifies in current sheet; default to server sheet
|
|
|
|
|
pChatSheet = GetActiveChatSheet();
|
|
|
|
|
if (!pChatSheet) pChatSheet = GetServerSheet();
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
else if (pMsg->getType() == MSG_Status || !sUser.getLength())
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
// server message
|
|
|
|
|
pChatSheet = GetServerSheet();
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
else if (sUser == pIRCClient->getUserName())
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
// private message by myself
|
|
|
|
|
// message to a service into service window; otherwise (new) query
|
|
|
|
|
if (IsServiceName(pMsg->getTarget()))
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
pChatSheet = GetServerSheet();
|
|
|
|
|
fMsgToService = true;
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
else
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
pChatSheet = OpenQuery(pMsg->getTarget(), true, NULL);
|
|
|
|
|
if (pChatSheet) pChatSheet->SetChatTitle(pMsg->getTarget());
|
2010-03-27 16:05:02 +00:00
|
|
|
|
}
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2010-03-27 16:05:02 +00:00
|
|
|
|
else
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
// private message
|
|
|
|
|
pChatSheet = OpenQuery(sUser.getData(), false, sIdent.getData());
|
|
|
|
|
if (pChatSheet) pChatSheet->SetChatTitle(pMsg->getSource());
|
|
|
|
|
}
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
if (pChatSheet)
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
// get message formatting and color
|
|
|
|
|
StdStrBuf sMsg; uint32_t dwClr = C4GUI_MessageFontClr;
|
|
|
|
|
switch (pMsg->getType())
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
|
|
|
|
case MSG_Server:
|
|
|
|
|
sMsg.Format("- %s", pMsg->getData());
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MSG_Status:
|
|
|
|
|
sMsg.Format("- %s", pMsg->getData());
|
|
|
|
|
dwClr = C4GUI_InactMessageFontClr;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MSG_Notice:
|
|
|
|
|
if (sUser.getLength())
|
|
|
|
|
if (sUser != pIRCClient->getUserName())
|
|
|
|
|
sMsg.Format("-%s- %s", sUser.getData(), pMsg->getData());
|
2009-05-08 13:28:41 +00:00
|
|
|
|
else
|
2010-03-28 18:58:01 +00:00
|
|
|
|
sMsg.Format("-> -%s- %s", pMsg->getTarget(), pMsg->getData());
|
|
|
|
|
else
|
|
|
|
|
sMsg.Format("* %s", pMsg->getData());
|
|
|
|
|
dwClr = C4GUI_NotifyFontClr;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MSG_Message:
|
|
|
|
|
if (fMsgToService)
|
|
|
|
|
sMsg.Format("-> *%s* %s", pMsg->getTarget(), pMsg->getData());
|
|
|
|
|
else if (sUser.getLength())
|
|
|
|
|
sMsg.Format("<%s> %s", sUser.getData(), pMsg->getData());
|
|
|
|
|
else
|
|
|
|
|
sMsg.Format("* %s", pMsg->getData());
|
|
|
|
|
break;
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
2010-03-28 18:58:01 +00:00
|
|
|
|
case MSG_Action:
|
|
|
|
|
if (sUser.getLength())
|
|
|
|
|
sMsg.Format("* %s %s", sUser.getData(), pMsg->getData());
|
|
|
|
|
else
|
|
|
|
|
sMsg.Format("* %s", pMsg->getData());
|
|
|
|
|
break;
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
2010-03-28 18:58:01 +00:00
|
|
|
|
default:
|
|
|
|
|
sMsg.Format("??? %s", pMsg->getData());
|
|
|
|
|
dwClr = C4GUI_ErrorFontClr;
|
|
|
|
|
break;
|
2009-05-08 13:28:41 +00:00
|
|
|
|
}
|
2010-03-28 18:58:01 +00:00
|
|
|
|
pChatSheet->AddTextLine(sMsg.getData(), dwClr);
|
2009-05-08 13:28:41 +00:00
|
|
|
|
}
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
// OK; all messages processed. Delete overflow messages.
|
|
|
|
|
pIRCClient->MarkMessageLogRead();
|
|
|
|
|
// update selected channel (users, topic)
|
|
|
|
|
ChatSheet *pActiveSheet = GetActiveChatSheet();
|
|
|
|
|
if (pActiveSheet) pActiveSheet->Update(false);
|
|
|
|
|
// update title
|
|
|
|
|
UpdateTitle();
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
|
|
C4ChatControl::ChatSheet *C4ChatControl::OpenQuery(const char *szForNick, bool fSelect, const char *szIdentFallback)
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
// search existing query first
|
|
|
|
|
ChatSheet *pChatSheet = GetSheetByTitle(szForNick, ChatSheet::CS_Query);
|
|
|
|
|
// not found but ident given? Then search for ident as well
|
|
|
|
|
if (!pChatSheet && szIdentFallback) pChatSheet = GetSheetByIdent(szIdentFallback, ChatSheet::CS_Query);
|
|
|
|
|
// auto-open query if not found
|
|
|
|
|
if (!pChatSheet)
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
pTabChats->AddCustomSheet(pChatSheet = new ChatSheet(this, szForNick, szIdentFallback, ChatSheet::CS_Query));
|
|
|
|
|
// initial chat title just user name; changed to user name+ident if a message from the nick arrives
|
|
|
|
|
pChatSheet->SetChatTitle(szForNick);
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
else
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
// query already open: Update user name if necessary
|
|
|
|
|
pChatSheet->SetTitle(szForNick);
|
|
|
|
|
if (szIdentFallback) pChatSheet->SetIdent(szIdentFallback);
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
if (fSelect) pTabChats->SelectSheet(pChatSheet, true);
|
|
|
|
|
return pChatSheet;
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
|
|
void C4ChatControl::UpdateTitle()
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
StdCopyStrBuf sNewTitle;
|
|
|
|
|
if (pTabMain->GetActiveSheetIndex() == 0)
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
// login title
|
|
|
|
|
sNewTitle = LoadResStr("IDS_CHAT_NOTCONNECTED");
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
else
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
// login by active sheet
|
|
|
|
|
ChatSheet *pActiveSheet = GetActiveChatSheet();
|
|
|
|
|
if (pActiveSheet)
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
sNewTitle = pActiveSheet->GetChatTitle();
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
else
|
|
|
|
|
sNewTitle = "";
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
// call update proc only if title changed
|
|
|
|
|
if (sTitle != sNewTitle)
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-11-25 18:38:54 +00:00
|
|
|
|
sTitle.Take(std::move(sNewTitle));
|
2009-05-08 13:28:41 +00:00
|
|
|
|
if (pTitleChangeBC) pTitleChangeBC->OnOK(sTitle);
|
|
|
|
|
}
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
|
|
bool C4ChatControl::DlgEnter()
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
// enter on connect button connects
|
|
|
|
|
if (GetDlg()->GetFocus() == pBtnLogin) { OnConnectBtn(pBtnLogin); return true; }
|
|
|
|
|
return false;
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
|
|
void C4ChatControl::ClearChatSheets()
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
pTabChats->ClearSheets();
|
|
|
|
|
// add server sheet
|
|
|
|
|
pTabChats->AddCustomSheet(new ChatSheet(this, LoadResStr("IDS_CHAT_SERVER"), NULL, ChatSheet::CS_Server));
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
|
|
bool C4ChatControl::ProcessInput(const char *szInput, ChatSheet *pChatSheet)
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
CStdLock Lock(pIRCClient->getCSec());
|
|
|
|
|
// process chat input - return false if no more pasting is to be done (i.e., on /quit or /part in channel)
|
|
|
|
|
bool fResult = true;
|
|
|
|
|
bool fIRCSuccess = true;
|
|
|
|
|
// not connected?
|
|
|
|
|
if (!pIRCClient->IsConnected())
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
pChatSheet->DoError(LoadResStr("IDS_ERR_NOTCONNECTEDTOSERVER"));
|
|
|
|
|
return fResult;
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
// safety
|
|
|
|
|
if (!szInput || !*szInput || !pChatSheet) return fResult;
|
|
|
|
|
// check confidential data
|
2009-07-08 17:54:54 +00:00
|
|
|
|
if (Config.IsConfidentialData(szInput))
|
|
|
|
|
{
|
|
|
|
|
pChatSheet->DoError(LoadResStr("IDS_ERR_WARNINGYOUWERETRYINGTOSEN"));
|
|
|
|
|
return fResult;
|
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
// command?
|
|
|
|
|
if (*szInput == '/' && !SEqual2NoCase(szInput + 1, "me "))
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2010-11-25 18:02:23 +00:00
|
|
|
|
StdStrBuf sCommand, sParam(""); sCommand.Copy(szInput+1);
|
2009-05-08 13:28:41 +00:00
|
|
|
|
sCommand.SplitAtChar(' ', &sParam);
|
2010-11-25 18:02:23 +00:00
|
|
|
|
if (SEqualNoCase(sCommand.getData(), "help"))
|
|
|
|
|
{
|
|
|
|
|
pChatSheet->DoError(LoadResStr("IDS_ERR_HELPCMD"));
|
|
|
|
|
fResult = false;
|
|
|
|
|
}
|
|
|
|
|
else if (SEqualNoCase(sCommand.getData(), "quit"))
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
// query disconnect from IRC server
|
|
|
|
|
fIRCSuccess = pIRCClient->Quit(sParam.getData());
|
|
|
|
|
fResult = false;
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
else if (SEqualNoCase(sCommand.getData(), "part"))
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
// part channel. Default to current channel if typed within a channel
|
|
|
|
|
if (!sParam.getLength() && pChatSheet->GetSheetType() == ChatSheet::CS_Channel)
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
sParam.Copy(pChatSheet->GetIdent());
|
|
|
|
|
fResult = false;
|
|
|
|
|
}
|
2010-03-28 18:58:01 +00:00
|
|
|
|
fIRCSuccess = pIRCClient->Part(sParam.getData());
|
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
else if (SEqualNoCase(sCommand.getData(), "join") || SEqualNoCase(sCommand.getData(), "j"))
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
if (!sParam.getLength()) sParam.Copy(Config.IRC.Channel);
|
|
|
|
|
fIRCSuccess = pIRCClient->Join(sParam.getData());
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
else if (SEqualNoCase(sCommand.getData(), "notice") || SEqualNoCase(sCommand.getData(), "msg"))
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
bool fMsg = SEqualNoCase(sCommand.getData(), "msg");
|
|
|
|
|
StdStrBuf sMsg;
|
|
|
|
|
if (!sParam.SplitAtChar(' ', &sMsg) || !sMsg.getLength())
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
pChatSheet->DoError(FormatString(LoadResStr("IDS_ERR_INSUFFICIENTPARAMETERS"), sCommand.getData()).getData());
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
else
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
if (fMsg)
|
|
|
|
|
fIRCSuccess = pIRCClient->Message(sParam.getData(), sMsg.getData());
|
|
|
|
|
else
|
|
|
|
|
fIRCSuccess = pIRCClient->Notice(sParam.getData(), sMsg.getData());
|
|
|
|
|
}
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
else if (SEqualNoCase(sCommand.getData(), "raw"))
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
if (!sParam.getLength())
|
|
|
|
|
pChatSheet->DoError(FormatString(LoadResStr("IDS_ERR_INSUFFICIENTPARAMETERS"), sCommand.getData()).getData());
|
|
|
|
|
else
|
|
|
|
|
fIRCSuccess = pIRCClient->Send(sParam.getData());
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
else if (SEqualNoCase(sCommand.getData(), "ns") || SEqualNoCase(sCommand.getData(), "cs") || SEqualNoCase(sCommand.getData(), "ms"))
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
if (!sParam.getLength())
|
|
|
|
|
pChatSheet->DoError(FormatString(LoadResStr("IDS_ERR_INSUFFICIENTPARAMETERS"), sCommand.getData()).getData());
|
|
|
|
|
else
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
const char *szMsgTarget;
|
2010-03-28 18:58:01 +00:00
|
|
|
|
if (SEqualNoCase(sCommand.getData(), "ns")) szMsgTarget = "NickServ";
|
2009-05-08 13:28:41 +00:00
|
|
|
|
else if (SEqualNoCase(sCommand.getData(), "cs")) szMsgTarget = "ChanServ";
|
|
|
|
|
else szMsgTarget = "MemoServ";
|
|
|
|
|
fIRCSuccess = pIRCClient->Message(szMsgTarget, sParam.getData());
|
|
|
|
|
}
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
else if (SEqualNoCase(sCommand.getData(), "query") || SEqualNoCase(sCommand.getData(), "q"))
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
if (!sParam.getLength())
|
|
|
|
|
pChatSheet->DoError(FormatString(LoadResStr("IDS_ERR_INSUFFICIENTPARAMETERS"), sCommand.getData()).getData());
|
|
|
|
|
else
|
2010-11-25 18:02:23 +00:00
|
|
|
|
{
|
|
|
|
|
StdStrBuf sMsg;
|
|
|
|
|
sParam.SplitAtChar(' ', &sMsg);
|
2009-05-08 13:28:41 +00:00
|
|
|
|
OpenQuery(sParam.getData(), true, NULL);
|
2010-11-25 18:02:23 +00:00
|
|
|
|
}
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
else if (SEqualNoCase(sCommand.getData(), "nick"))
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
|
|
|
|
if (C4InVal::ValidateString(sParam, C4InVal::VAL_IRCName))
|
2009-05-08 13:28:41 +00:00
|
|
|
|
pChatSheet->DoError(FormatString(LoadResStr("IDS_ERR_INVALIDNICKNAME2"), sCommand.getData()).getData());
|
2010-03-27 16:05:02 +00:00
|
|
|
|
else
|
|
|
|
|
fIRCSuccess = pIRCClient->ChangeNick(sParam.getData());
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
else
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
// unknown command
|
|
|
|
|
pChatSheet->DoError(FormatString(LoadResStr("IDS_ERR_UNKNOWNCMD"), sCommand.getData()).getData());
|
|
|
|
|
}
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
else
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
// regular chat input: Send as message to current channel/user
|
|
|
|
|
const char *szMsgTarget;
|
|
|
|
|
ChatSheet::SheetType eSheetType = pChatSheet->GetSheetType();
|
|
|
|
|
if (eSheetType == ChatSheet::CS_Server)
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
pChatSheet->DoError(LoadResStr("IDS_ERR_NOTONACHANNEL"));
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
else
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
szMsgTarget = pChatSheet->GetTitle();
|
2010-03-27 16:05:02 +00:00
|
|
|
|
if (*szInput == '/') // action
|
2010-03-28 18:58:01 +00:00
|
|
|
|
fIRCSuccess = pIRCClient->Action(szMsgTarget, szInput+4);
|
2010-03-27 16:05:02 +00:00
|
|
|
|
else
|
2010-03-28 18:58:01 +00:00
|
|
|
|
fIRCSuccess = pIRCClient->Message(szMsgTarget, szInput);
|
2009-05-08 13:28:41 +00:00
|
|
|
|
}
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
// IRC sending error? log it
|
|
|
|
|
if (!fIRCSuccess)
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
pChatSheet->DoError(pIRCClient->GetError());
|
|
|
|
|
}
|
2010-03-28 18:58:01 +00:00
|
|
|
|
return fResult;
|
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
|
|
void C4ChatControl::UserQueryQuit()
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
// still connected? Then confirm first
|
|
|
|
|
if (pIRCClient->IsActive())
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
if (!GetScreen()->ShowMessageModal(LoadResStr("IDS_MSG_DISCONNECTFROMSERVER"), LoadResStr("IDS_DLG_CHAT"), C4GUI::MessageDialog::btnOKAbort, C4GUI::Ico_Confirm, NULL))
|
|
|
|
|
return;
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
// disconnect from server
|
|
|
|
|
pIRCClient->Close();
|
|
|
|
|
// change back to login page
|
|
|
|
|
UpdateShownPage();
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* C4ChatDlg */
|
|
|
|
|
|
|
|
|
|
C4ChatDlg *C4ChatDlg::pInstance = NULL;
|
|
|
|
|
|
|
|
|
|
C4ChatDlg::C4ChatDlg() : C4GUI::Dialog(100, 100, "IRC", false)
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
// child elements - positioned later
|
|
|
|
|
pChatCtrl = new C4ChatControl(&Application.IRCClient);
|
|
|
|
|
pChatCtrl->SetTitleChangeCB(new C4GUI::InputCallback<C4ChatDlg>(this, &C4ChatDlg::OnChatTitleChange));
|
|
|
|
|
AddElement(pChatCtrl);
|
|
|
|
|
C4Rect rcDefault(0,0,10,10);
|
|
|
|
|
//pBtnClose = new C4GUI::CallbackButton<C4ChatDlg>(LoadResStr("IDS_DLG_EXIT"), rcDefault, &C4ChatDlg::OnExitBtn);
|
|
|
|
|
//AddElement(pBtnClose);
|
|
|
|
|
// del dlg when closed
|
|
|
|
|
SetDelOnClose();
|
|
|
|
|
// set initial element positions
|
|
|
|
|
UpdateSize();
|
|
|
|
|
// intial focus
|
|
|
|
|
SetFocus(GetDefaultControl(), false);
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
|
|
C4ChatDlg::~C4ChatDlg()
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
|
|
C4ChatDlg *C4ChatDlg::ShowChat()
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
if (!pInstance)
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
pInstance = new C4ChatDlg();
|
2009-06-05 16:53:56 +00:00
|
|
|
|
pInstance->Show(::pGUI, true);
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
else
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-06-05 16:53:56 +00:00
|
|
|
|
::pGUI->ActivateDialog(pInstance);
|
2009-05-08 13:28:41 +00:00
|
|
|
|
}
|
2010-03-28 18:58:01 +00:00
|
|
|
|
return pInstance;
|
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
|
|
void C4ChatDlg::StopChat()
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
if (!pInstance) return;
|
|
|
|
|
pInstance->Close(false);
|
|
|
|
|
// 2do: Quit IRC
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
|
|
bool C4ChatDlg::ToggleChat()
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
if (pInstance && pInstance->IsShown())
|
|
|
|
|
StopChat();
|
|
|
|
|
else
|
|
|
|
|
ShowChat();
|
|
|
|
|
return true;
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
|
|
bool C4ChatDlg::IsChatActive()
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
// not if chat is disabled
|
|
|
|
|
if (!IsChatEnabled()) return false;
|
|
|
|
|
// check whether IRC is connected
|
2010-03-27 16:05:02 +00:00
|
|
|
|
return Application.IRCClient.IsActive();
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
|
|
bool C4ChatDlg::IsChatEnabled()
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
return true;
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
|
|
C4GUI::Control *C4ChatDlg::GetDefaultControl()
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
return pChatCtrl->GetDefaultControl();
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
|
|
bool C4ChatDlg::DoPlacement(C4GUI::Screen *pOnScreen, const C4Rect &rPreferredDlgRect)
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
// ignore preferred rect; place over complete screen
|
|
|
|
|
C4Rect rcPos = pOnScreen->GetContainedClientRect();
|
|
|
|
|
rcPos.x += rcPos.Wdt/10; rcPos.Wdt -= rcPos.Wdt/5;
|
|
|
|
|
rcPos.y += rcPos.Hgt/10; rcPos.Hgt -= rcPos.Hgt/5;
|
|
|
|
|
SetBounds(rcPos);
|
|
|
|
|
return true;
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
|
|
void C4ChatDlg::OnClosed(bool fOK)
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
// callback when dlg got closed
|
|
|
|
|
pInstance = NULL;
|
|
|
|
|
typedef C4GUI::Dialog ParentClass;
|
|
|
|
|
ParentClass::OnClosed(fOK);
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
|
|
void C4ChatDlg::OnShown()
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
// callback when shown - should not delete the dialog
|
|
|
|
|
typedef C4GUI::Dialog ParentClass;
|
|
|
|
|
ParentClass::OnShown();
|
|
|
|
|
pChatCtrl->OnShown();
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
|
|
void C4ChatDlg::UpdateSize()
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
// parent update
|
|
|
|
|
typedef C4GUI::Dialog ParentClass;
|
|
|
|
|
ParentClass::UpdateSize();
|
|
|
|
|
// position child elements
|
|
|
|
|
C4GUI::ComponentAligner caMain(GetContainedClientRect(), 0,0);
|
|
|
|
|
//C4GUI::ComponentAligner caBottom(caMain.GetFromBottom(C4GUI_ButtonHgt+C4GUI_DefDlgIndent*2), C4GUI_DefDlgIndent,C4GUI_DefDlgIndent);
|
|
|
|
|
pChatCtrl->SetBounds(caMain.GetAll());
|
|
|
|
|
//pBtnClose->SetBounds(caBottom.GetFromLeft(100));
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
|
|
void C4ChatDlg::OnExitBtn(C4GUI::Control *btn)
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
UserClose(false);
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
|
|
void C4ChatDlg::OnChatTitleChange(const StdStrBuf &sNewTitle)
|
2010-03-28 18:58:01 +00:00
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
SetTitle(FormatString("%s - %s", LoadResStr("IDS_DLG_CHAT"), sNewTitle.getData()).getData());
|
2010-03-28 18:58:01 +00:00
|
|
|
|
}
|