unit engine;
{ AdvChat - a simple chat program }
{ Copyright (C) 2004 Patulea Andrei }
{ }
{ 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 }
{ }
{ 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}
interface
uses ScktComp,uRoomChatWindow,uPrivateChatWindow,Forms,Dialogs,SysUtils;
const
end_line = '#13#10';
s_pmsg = '!pmsg'; //!pmsg:fromuser(touser):msg -private chat
s_roommsg = '!roommsg'; //!roommsg:nick:room:msg;
s_joined = '!joined'; // !joined:room opens a new room window
s_joinroom = '!joinroom'; // !join:room -client request to join a room
s_members = '!members'; // !members:mem1,mem2,... - fills the list with users
s_newmember = '!newmember'; //!newmember:nick:room - add a user to a room
s_mempart = '!mempart'; //!mempart:nick:room - removes a user form the list
s_part = '!part'; //!part:roomname client sends that he parts the room
type TNick = String[14];
TRoom_name = String[20];
TRoom = record
Free_slot : boolean;
RoomName : TRoom_name;
end;
TUser = record
Free : boolean;
Nick : String[14];
Socket: Integer;
Chats : array of TRoom_name;
end;
var Users : array of TUser;
aServerSock : TServerSocket;
aClientSock : TClientSocket;
ChatRooms : array of tRoomChatWindow;
PrivateChats : array of tPrivateChatWindow;
procedure MsgToHandle(sHandle: integer; raw_msg: string);
procedure MsgToUser(var aUser : TUser; raw_msg : string);
procedure MsgToNick(aNick : TNick ;raw_msg: string);
procedure MsgToAllInRoom(aRoom: TRoom_name; raw_msg: string);
procedure JoinUserToRoom(aRoom : tRoom_name; var aUser : TUser);
procedure PartUserFromRoom(aRoom: tRoom_name;var aUser: TUser);
procedure client_handle_rcvd_line(var Line : string);
procedure server_handle_rcvd_line(var Line : string; aHandle:integer);
function GetNickFromHandle(sHandle:integer): TNick;
function GetIndexFromHandle(sHandle:integer) : Integer;
function IsUserInRoom(aRoom: tRoom_name;var aUser : TUser): boolean;
function GetUserIndexFromNick(aNick : tNick): integer;
function GetRoomIndex(aRoom : tRoom_name): integer;
implementation
uses uServerMain;
//this send a message to a socket handle
//aceasta procedura trmite un mesaj cunoscand numai Handle-ul
procedure MsgToHandle(sHandle: integer; raw_msg: string);
var I : Integer;
begin
Application.ProcessMessages;
For i := 0 to (aServerSock.Socket.ActiveConnections -1) //search for the handle
do if (aServerSock.Socket.Connections[i].SocketHandle = sHandle)
then begin
aServerSock.Socket.Connections[i].SendText(raw_msg+end_line);//send it
exit;
end;
end;
procedure MsgToUser(var aUser : TUser; raw_msg : string);
begin
MsgToHandle(aUser.Socket,raw_msg);
end;
procedure MsgToNick(aNick : TNick;raw_msg: string);
var i: integer;
begin
For i := Low(Users) to High(Users) do
If (Users[i].Free = False) and (Users[i].Nick = aNick)
then begin
MsgToUser(Users[i],raw_msg);
exit;
end;
end;
function GetIndexFromHandle(sHandle:integer): Integer;
var i: integer;
begin
For i := low(Users) to High(Users) do
If (Users[i].Free = False) and (Users[i].Socket = sHandle)
then begin
Result := i;
exit;
end;
end;
function IsUserInRoom(aRoom: tRoom_name;var aUser : TUser): boolean;
var i: integer;
begin
Result := False;
if (aRoom = '') then exit;
for i := low(aUser.Chats) to High(aUser.Chats) do
If (aUser.Chats[i] = aRoom)
then begin
Result := True;
exit;
end;
end;
procedure MsgToAllInRoom(aRoom: TRoom_name; raw_msg: string);
var i: Integer;
begin
if (aRoom = '') then exit;
For i := Low(Users) to High(Users) do
If IsUserInRoom(aRoom,Users[i]) then
MsgToUser(Users[i],raw_msg);
end;
function GetUserIndexFromNick(aNick : tNick): integer;
var I : Integer;
begin
if (aNick = '') then exit;
Result := -1;
if (aNick = '') then exit;
for i := Low(Users) to High(Users) do
if (Users[i].Free = False) and (Users[i].Nick = aNick)
then begin
Result := i;
exit;
end;
end;
procedure JoinUserToRoom(aRoom : tRoom_name;var aUser : TUser);
var i,j: integer;
members : String;
NoSpace : boolean;
begin
if (aRoom = '') then exit;
members := (s_members+':'+aRoom+':');
for i := Low(Users) to High(Users) do
if IsUserInRoom(aRoom,Users[i]) then
begin
if (members <> (s_members+':'+aRoom+':')) then members := members +','+Users[i].Nick;
if (members = (s_members+':'+aRoom+':')) then members := members + Users[i].Nick;
end;
MsgToHandle(aUser.Socket,s_joined+':'+aRoom);
MsgToHandle(aUser.Socket,members);
MsgToAllInRoom(aRoom,s_newmember+':'+aUser.Nick+':'+aRoom);
{
j := High(aUser.Chats);
if (j = 0) then begin
SetLength(aUser.Chats,1);
aUser.Chats[1].Free_slot := True;
end;
NoSpace := True;
for i := Low(aUser.Chats) to High(aUser.Chats) do
if aUser.Chats[i].Free_slot then begin
aUser.Chats[i].RoomName := aRoom;
aUser.Chats[i].Free_slot := False;
NoSpace := False;
end;
}
end;
procedure PartUserFromRoom(aRoom: tRoom_name;var aUser: TUser);
var i:Integer;
begin
if (aRoom = '') then exit;
MsgToAllInRoom(aRoom,s_mempart+':'+aUser.Nick+':'+aRoom);
//MsgToUser(aUser,s_leftroom+':'+aRoom);
For i := Low(aUser.Chats) to High(aUser.Chats) do
If (aUser.Chats[i] = aRoom)
then begin
aUser.Chats[i] := '';
exit;
end;
end;
function GetRoomIndex(aRoom : tRoom_name): integer;
var i: integer;
begin
for i := Low(ChatRooms) to High(ChatRooms) do
if (ChatRooms[i].RoomName = aRoom) then
begin
Result := i;
exit;
end;
end;
function GetNickFromHandle(sHandle:integer): TNick;
var i: integer;
begin
for i := Low(Users) to High(Users) do
if (Users[i].Socket = sHandle) then
begin
Result := Users[i].Nick;
exit;
end;
end;
procedure client_handle_rcvd_line(var Line : string);
var p,i,k: integer;
comm, s1,s2 :string;
room : tRoom_name;
nick : tNick;
found_chat_window : Boolean;
begin
p := pos(':',line);
if (p = 0) then comm := line;
if (p <> 0) then comm := copy(line,1,p-1);
//!pmsg:fromnick:msg
if (comm = s_pmsg) then begin
Delete(Line,1,p+1);
p := pos(':',line);
nick := Copy(line,1,p-1); //fromnick
s2 := Copy(line,p+1,Length(line));
found_chat_window := False;
for i:= Low(PrivateChats) to High(PrivateChats) do
if (PrivateChats[i].aUser = nick)then
begin
PrivateChats[i].AddChatLine(nick,s2) ;
found_chat_window := True;
end;
if (not found_chat_window) then begin
SetLength(PrivateChats,High(PrivateChats)+1);
i := High(PrivateChats);
PrivateChats[i].Create(Application);
PrivateChats[i].Show;
PrivateChats[i].aUser := nick;
PrivateChats[i].AddChatLine(nick,s2);
PrivateChats[i].Caption := 'Private Chat with: '+ nick;
end;
end; //end of !pmsg command
//!joined:room
if (comm = s_joined) then begin
p := pos(':',line);
room := Copy(line,p+1,Length(Line));
SetLength(ChatRooms,High(ChatRooms)+1);
i := High(ChatRooms);
ChatRooms[i].Create(Application);
ChatRooms[i].RoomName := room;
ChatRooms[i].Caption := room;
end; //end of joined command
//!members:room:mem1,mem2...
if (comm = s_members) then begin
p:= pos(':', line); //!members:room:mem1,mem2..
Delete(Line,1,p+1); //room:mem1,mem2...
p := pos(':',Line);
room := Copy(Line,1,p-1); //room = roomname
Delete(Line,1,p+1); //mem1,mem2...
k := GetRoomIndex(room);
ChatRooms[k].memberlist.Clear;
while (p <> 0) do begin
p := pos(',',Line);
ChatRooms[k].memberlist.Items.Add(Copy(Line,1,p-1));
Delete(Line,1,p+1);
end;
end; //end of members command
// !roommsg:nick:room:msg
if (comm = s_roommsg) then begin
p := pos(':',Line);
Delete(Line,1,p+1); //nick:room:msg
p := pos(':',Line);
nick := Copy(Line,1,p-1); //sender
Delete(Line,1,p+1); //room:msg
p := pos(':',Line);
room := Copy(line,1,p-1); // roomname
Delete(Line,1,p+1); //msg (line = msg);
for i := Low(ChatRooms) to High(ChatRooms) do
if (ChatRooms[i].RoomName = room) then
begin
ChatRooms[i].AddChatLine(nick,line);
exit;
end;
end;
//!newmember:nick:room
if (comm = s_newmember) then begin
p := pos(':',Line);
Delete(Line,1,p+1); //nick:room
p := pos(':',Line);
nick := Copy(Line,1,p-1); // members nickname
room := Copy(Line,p+1,Length(Line)); //room name
ChatRooms[GetRoomIndex(room)].memberlist.Items.Add(nick)
end; // end of newmember command
//!mempart:nick:room
if (comm = s_mempart) then begin
p := pos(':',Line);
Delete(Line,1,p+1); //nick:room
p := pos(':',Line);
nick := Copy(Line,1,p-1); // nickname
room := Copy(Line,p+1,Length(Line)); //room name
k := ChatRooms[GetRoomIndex(room)].memberlist.Count -1;
for i:= 0 to k do
if (ChatRooms[GetRoomIndex(room)].memberlist.Items.Strings[i] = nick)
then begin
ChatRooms[GetRoomIndex(room)].memberlist.Items.Delete(i);
exit;
end;
end;
end;
procedure server_handle_rcvd_line(var Line : string; aHandle: integer);
var p,i,k: integer;
comm, s1,s2 :string;
nick,nick1 : tNick;
room : tRoom_name;
begin
p := pos(':',line);
if (p = 0) then comm := line;
if (p <> 0) then comm := copy(line,1,p-1);
// client sends !pmsg:nick:msg
if (comm = s_pmsg) then begin
p := pos(':',Line);
Delete(Line,1,p+1); //nick:msg
p := pos(':',Line);
Delete(Line,1,p+1);//line = msg
nick := Copy(Line,1,p-1); // RECEIVERS nick
nick1 := GetNickFromHandle(aHandle); // SENDERS nick
MsgToNick(nick,s_pmsg+':'+nick1+':'+Line);
end; //end of !pmsg
//client sends !roommsg:room:msg
if (comm = s_roommsg) then begin
nick := GetNickFromHandle(aHandle); // SENDER nick
p := pos(':',Line);
Delete(Line,1,p+1); //room:msg
p := pos(':',Line);
room := Copy(Line,1,p-1); // room name
Delete(Line,1,p+1);// line = msg
MsgToAllInRoom(room,s_roommsg+':'+nick+':'+room+':'+Line);
end;// end of roommsg command
//client sends !joinroom:roomname
if (comm = s_joinroom) then begin
p := pos(':',Line);
room := Copy(Line,p+1,Length(Line)); //roomname
JoinUserToRoom(room,Users[GetIndexFromHandle(aHandle)]);
end; //end of joinroom command
if (comm = s_part) then begin
p := pos(':',Line);
room := Copy(Line,p+1,Length(Line));
PartUserFromRoom(room,Users[GetIndexFromHandle(aHandle)]);
end; //end of part command
end;
initialization
SetLength(Users,1); //initialization
end.