//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "ChatServerMainForm.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "IdBaseComponent"
#pragma link "IdComponent"
#pragma link "IdContext"
#pragma link "IdCustomTCPServer"
#pragma link "IdTCPServer"
#pragma resource "*.dfm"
TfrmChatServerMain *frmChatServerMain;
// For Unicode support
#define ENCODING
TEncoding* CharacterEncoding = TIdTextEncoding::UTF8;
//---------------------------------------------------------------------------
__fastcall TfrmChatServerMain::TfrmChatServerMain(TComponent* Owner) : TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TfrmChatServerMain::btnStartClick(TObject *Sender)
{
tcpServer->Active = true;
}
//---------------------------------------------------------------------------
void __fastcall TfrmChatServerMain::FormCreate(TObject *Sender)
{
mmoHistory->Align = alClient;
}
//---------------------------------------------------------------------------
void __fastcall TfrmChatServerMain::tcpServerExecute(TIdContext *AContext)
{
// Check message queue
String s = AContext->Connection->IOHandler->ReadLn("", 50);
// If no message, nothing to do
if (AContext->Connection->IOHandler->ReadLnTimedout)
return;
// Message received. What kind? (Currently only supports SEND and CMD)
if (!CompareText(s.SubString(1, 4), "SEND"))
{
UpdateOutput(s, dirRECV);
String msg = "MESG " + AContext->Binding()->PeerIP + ":" + AContext->Binding()->PeerPort;
msg += s.SubString(5, s.Length());
BroadcastMessage(Trim(msg));
}
else if (!CompareText(s.SubString(1, 3), "CMD"))
{
UpdateOutput(s, dirRECV);
TStringList *list = new TStringList;
list->DelimitedText = s;
list->Delimiter = ' ';
// Client wants to quit the session
if (!CompareText(list->Strings[1].SubString(1, 4), "QUIT"))
AContext->Connection->Disconnect();
delete list;
}
}
//---------------------------------------------------------------------------
void TfrmChatServerMain::UpdateOutput(const String& s, TDirection dir)
{
String d = "";
TColor attr = clBlack;
if (dir == dirSEND)
{
d = "SEND --> ";
attr = clBlue;
}
else if (dir == dirRECV)
{
d = "RECV <-- ";
attr = clRed;
}
/*
This works differently than I expected. If you set the attributes, and
then Add() lines to the control, everything works fine. But, if you
Insert() the lines, you need to insert them before setting the attribute.
If you don't, you'll get the new attribute applied to the item at index
0, which will be scrolled down to index 1 after the insert and will have
the new attribute applied.
*/
String str = d + s;
mmoHistory->Lines->BeginUpdate();
if (chkInsertLinesAtTop->Checked)
{
// Insert the line
mmoHistory->Lines->Insert(0, str);
// Select the line and then apply the color (attributes) to the selection
mmoHistory->SelStart = 0;
mmoHistory->SelLength = str.Length();
mmoHistory->SelAttributes->Color = attr;
}
else
{
mmoHistory->SelAttributes->Color = attr;
mmoHistory->Lines->Add(str);
}
mmoHistory->Lines->EndUpdate();
}
//---------------------------------------------------------------------------
void __fastcall TfrmChatServerMain::tcpServerConnect(TIdContext *AContext)
{
String port = AContext->Binding()->PeerPort;
String host = AContext->Binding()->PeerIP;
UpdateOutput("Connected: " + host + ":" + port);
#ifdef ENCODING
AContext->Connection->IOHandler->DefStringEncoding = CharacterEncoding;
#endif
AContext->Connection->IOHandler->WriteLn("MESG Server Welcome to Simple Chat!");
}
//---------------------------------------------------------------------------
void __fastcall TfrmChatServerMain::tcpServerDisconnect(TIdContext *AContext)
{
String port = AContext->Binding()->PeerPort;
String host = AContext->Binding()->PeerIP;
UpdateOutput("Disconnected: " + host + ":" + port);
AContext->Connection->IOHandler->WriteLn("Goodbye.");
}
//---------------------------------------------------------------------------
void __fastcall TfrmChatServerMain::tcpServerAfterBind(TObject *Sender)
{
for (int i = 0; i < tcpServer->Bindings->Count; i++)
{
String s = "Listening on ";
s += tcpServer->Bindings->Items[0]->IP;
s += ":";
s += tcpServer->Bindings->Items[0]->Port;
UpdateOutput(s);
}
}
//---------------------------------------------------------------------------
void TfrmChatServerMain::BroadcastMessage(const String& msg)
{
// Get list of clients (threads) and broadcast the message to each client.
TList *clients = tcpServer->Contexts->LockList();
for (int i = 0; i < clients->Count; i++)
{
TIdContext *context = reinterpret_cast<TIdContext *>(clients->Items[i]);
context->Connection->IOHandler->WriteLn(Trim(msg));
}
tcpServer->Contexts->UnlockList();
}
//---------------------------------------------------------------------------
void __fastcall TfrmChatServerMain::btnBroadcastClick(TObject *Sender)
{
String msg = "MESG Server " + ledtCommand->Text;
UpdateOutput(msg, dirSEND);
BroadcastMessage(msg);
}
//---------------------------------------------------------------------------