📄 chatpage.cpp
字号:
ChannelFrame->SendEdit->SetFocus();
// remove highlight from new page
PageCtrl->ActivePage->Highlighted = false;
}
//---------------------------------------------------------------------------
AnsiString TChatForm::FilterColors(AnsiString Text)
{
char* src = Text.c_str();
AnsiString Dst;
// This horror documented at:
// http://www.visualirc.net/tech-attrs.php
// http://www.ircle.com/colorfaq.shtml
// http://www.mirc.co.uk/help/color.txt
while(*src) {
switch(*src) {
case 2: // bold
case 15: // normal
case 17: // fixed pitch
case 18: // inverse
case 22: // italic
case 29: // italic
case 31: // underline
src++;
break;
case 3: // mirc color joyride
// Theory of operation: Remove aggressively. People who use colors
// tend to not have anything interesting to say anyway.
src++;
if(!isdigit(*src))
break;
for(int i = 0; i < 2 && isdigit(*src) && *src != ','; i++)
src++;
if(*src != ',')
break;
src++;
for(int i = 0; i < 2 && isdigit(*src); i++)
src++;
break;
case 4: // 6 digit hex color
src++;
for(int i = 0; i < 6 && *src; i++)
src++;
break;
default:
Dst += *src;
src++;
}
}
return Dst;
}
AnsiString TChatForm::GetToken(AnsiString* Text)
{
int pos = Text->Pos(" ");
if(pos == 0) {
AnsiString Token = *Text;
*Text = "";
return Token;
} else {
AnsiString Token = Text->SubString(1,pos-1);
*Text = Text->SubString(pos+1,Text->Length()-pos);
return Token;
}
}
typedef struct
{
char* Name; // command name
char* Args; // arguments
char* Descr; // command description
bool MustBeConnected; // true if command requires being connected
bool AllowedInStatus; // true if command is allowed in status window
} TIrcCmd;
static const TIrcCmd IrcCmdTable[] =
{
{ "help", "", "Shows list of available commands", false, true },
{ "topic", "", "Show current topic", true, false },
{ "query", "<user> [text]", "Open new window for this user and optionally send message", true, false },
{ "msg", "<user> <text>", "Send message to user without opening new window", true, true },
{ "notice", "<user> <text>", "Send notice to user", true, true },
{ "me", "<action>", "Perform action", true, false },
{ "join", "<room>", "Join room", true, true },
{ "part", "[room]", "Leave room", true, true },
{ "whois", "<user>", "Show info about user in status window", true, true },
{ "list", "", "Refresh list of rooms", true, true },
{ "nick", "<nickname>", "Change your current nickname", true, true },
{ "clear", "", "Clear screen", false, true },
{ "close", "", "Close window, leaves room if necessary", false, false},
{ "quit", "[message]", "Quit with message", true, true },
{ "raw", "<command>", "Send raw command to server", true, true },
{ "server", "[host] [port]", "Connect to another IRC server", false, true },
{ NULL, NULL, NULL, false, false }
};
void __fastcall TChatForm::ChannelFrameOnCommand(TChatChannelFrame* ChannelFrame,
AnsiString Text)
{
#define PRINT ChannelFrame->Print
const TIrcCmd* Cmd = NULL;
if(Text.Length() == 0)
return;
if(Text[1] == '/') {
AnsiString Name = GetToken(&Text).LowerCase();
for(int i = 0; IrcCmdTable[i].Name; i++) {
if(stricmp(IrcCmdTable[i].Name,Name.c_str() + 1) == 0) {
Cmd = &IrcCmdTable[i];
break;
}
}
if(!Cmd) {
PRINT(AnsiString("Unknown command: " + Name + " " + Text),ColInfo,false,true);
return;
}
} else {
// message to either channel or user but not a command
if(ChannelFrame == StatusFrame) {
PRINT(AnsiString("You are not in a room"),ColInfo,false,true);
return;
}
if(!Connected) {
PRINT("Not connected",ColInfo,false,true);
return;
}
PRINT(AnsiString("<") + Irc->UserInfo->Nick + "> " + Text,ColOwn,true);
Irc->Say(ChannelFrame->GetChannel(), Text);
return;
}
// filter commands invalid in status window
if(ChannelFrame == StatusFrame && !Cmd->AllowedInStatus) {
PRINT(AnsiString("This command is only valid in a room"),ColInfo,false,true);
return;
}
// filter commands invalid while not connected
if(Cmd->MustBeConnected && !Connected) {
PRINT(AnsiString("This command is only valid when connected"),ColInfo,false,true);
return;
}
// now handle the commands
string CmdName = Cmd->Name;
if(CmdName == "help") {
PRINT("Available commands:",ColInfo,false,true);
for(int i = 0; IrcCmdTable[i].Name; i++) {
AnsiString Line;
Line.printf("/%-6s %-13s - %s", IrcCmdTable[i].Name,
IrcCmdTable[i].Args, IrcCmdTable[i].Descr);
PRINT(Line,ColInfo,false,true);
}
} else if(CmdName == "topic") {
if(ChannelFrame->IsUserChat()) {
PRINT("Your a not in a room",ColInfo,false,true);
return;
}
Irc->GetTopic(ChannelFrame->GetChannel());
} else if(CmdName == "query") {
AnsiString User = GetToken(&Text);
if(User == "") {
PRINT("/query: Insufficient parameters",ColInfo,false,true);
return;
}
// now either find window for this user or create one
TChatChannelFrame* NewFrame = GetChannelFrame(User);
if(!NewFrame) {
// only open window if user exists in channel this was typed into
if(!ChannelFrame->ExistsUser(User) && ChannelFrame != StatusFrame) {
PRINT("/query: User '" + User + "' not in this channel",ColInfo,false,true);
return;
}
NewFrame = NewChannelFrame(User,true);
NewFrame->Print(AnsiString("Now talking to ") + User,ColJoin,true,true);
}
// if user specified a message, send it
if(Text != "") {
NewFrame->Print(AnsiString("<") + Irc->UserInfo->Nick + "> " + Text,ColOwn,true);
Irc->Say(User,Text);
}
} else if(CmdName == "msg") {
AnsiString User = GetToken(&Text);
if(User == "" || Text == "") {
PRINT("/msg: Insufficient parameters",ColInfo,false,true);
return;
}
PRINT(AnsiString("-> *") + User + "* " + Text,ColOwn,true,false);
Irc->Say(User,Text);
} else if(CmdName == "notice") {
AnsiString User = GetToken(&Text);
if(User == "" || Text == "") {
PRINT("/notice: Insufficient parameters",ColInfo,false,true);
return;
}
PRINT(AnsiString("-> -") + User + "- " + Text,ColOwn,true,false);
Irc->Notice(User,Text);
} else if(CmdName == "me") {
if(Text == "") {
PRINT("/me: Insufficient parameters",ColInfo,false,true);
return;
}
PRINT(Irc->CurrentNick + " " + Text,ColAction,true,true);
Irc->CTCPQuery(ChannelFrame->GetChannel(),"ACTION",Text);
} else if(CmdName == "join") {
if(Text == "") {
PRINT("/join: Insufficient parameters",ColInfo,false,true);
return;
}
// if there is already a window for the channel switch now
TChatChannelFrame* Frame = GetChannelFrame(Text);
if(Frame)
PageCtrl->ActivePage = (TTabSheet*)Frame->Parent;
// actually join channel
Irc->Join(Text);
} else if(CmdName == "part") {
if(Text == "" && !ChannelFrame->IsUserChat())
Text = ChannelFrame->GetChannel();
if(Text == "") {
PRINT("/part: Insufficient parameters",ColInfo,false,true);
return;
}
Irc->Part(Text,"");
} else if(CmdName == "whois") {
if(Text == "") {
PRINT("/whois: Insufficient parameters",ColInfo,false,true);
return;
}
Irc->Raw(AnsiString("WHOIS ") + Text);
} else if(CmdName == "list") {
if(ListingChannels) {
PRINT("/list: Already refreshing rooms",ColInfo,false,true);
return;
}
ChannelsListView->Clear();
ListingChannels = true;
Irc->Raw("LIST");
} else if(CmdName == "nick") {
if(Text == "") {
PRINT("/nick: Insufficient parameters",ColInfo,false,true);
return;
}
Irc->Raw(AnsiString("NICK ") + Text);
} else if(CmdName == "raw") {
if(Text == "") {
PRINT("/raw: Insufficient parameters",ColInfo,false,true);
return;
}
Irc->Raw(Text);
} else if(CmdName == "quit") {
Irc->Quit(Text);
} else if(CmdName == "server") {
AnsiString Host = GetToken(&Text);
if(Host == "")
Connect();
else if (Text == "" || StrToInt64(Text) <= 0)
Connect(Host,6667);
else
Connect(Host,StrToInt64(Text));
} else if(CmdName == "clear") {
ChannelFrame->RecvRichEdit->Clear();
if(ChannelFrame->RecvRichEdit->Focused())
ChannelFrame->SendEdit->SetFocus();
} else if(CmdName == "close") {
// part just in case
if(!ChannelFrame->IsUserChat())
Irc->Part(ChannelFrame->GetChannel(),"");
DeleteChannelFrame(ChannelFrame);
} else {
PRINT("Known command not handled. This is a bug!",ColWarn,false,true);
return;
}
#undef PRINT
}
//---------------------------------------------------------------------------
void __fastcall TChatForm::ChannelsListViewCompare(TObject *Sender,
TListItem *Item1, TListItem *Item2, int Data, int &Compare)
{
switch(Data) {
case 1: // users
{
int a = Item1->SubItems->Strings[0].ToInt();
int b = Item2->SubItems->Strings[0].ToInt();
Compare = a < b ? 1 : (a > b ? -1 : 0);
break;
}
case 2: // topic
Compare = Item1->SubItems->Strings[1].AnsiCompareIC(Item2->SubItems->Strings[1]);
break;
case 0: // channel name
default:
Compare = Item1->Caption.AnsiCompareIC(Item2->Caption);
break;
};
}
void __fastcall TChatForm::ChannelsListViewColumnClick(TObject *Sender,
TListColumn *Column)
{
ChannelsListView->CustomSort(NULL,Column->Index);
}
void __fastcall TChatForm::ChannelsListViewDblClick(TObject *Sender)
{
if(!ChannelsListView->ItemFocused)
return;
// simulate join command from status window
ChannelFrameOnCommand(StatusFrame,AnsiString("/join ") + ChannelsListView->ItemFocused->Caption);
}
//---------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -