#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <errno.h>
#include <ctype.h>
#include <conio.h>
#include <wslib.h>
#include <misclib.h>
#include "connap.h"
#include "io.h"
#include "connect.h"
#include "command.h"
#include "chat.h"
#include "message.h"
#include "sound.h"
#include "util.h"
CHAN *channels = NULL;
PRIV *privs = NULL;
PING *pings = NULL;
char *join_chan = NULL;
char *priv_nick = NULL;
void ping(char *nick)
{
PING *new_ping, *ping, *prev_ping = NULL;
for (ping = pings; ping; ping = ping->next) {
if (! strcmp(ping->nick, nick))
break;
prev_ping = ping;
}
if (ping) {
if (prev_ping) {
prev_ping->next = ping->next;
} else {
pings = pings->next;
}
free(ping->nick);
free((char*)ping);
}
new_ping = (PING*)malloc(sizeof(PING));
new_ping->nick = new_string(nick);
new_ping->start = time(NULL);
new_ping->next = NULL;
if (! pings)
pings = new_ping;
else {
for (ping = pings; ping->next; ping = ping->next);
ping->next = new_ping;
}
if (send_msg(MSG_CLIENT_PING, new_ping->nick))
disconnect(ws_strerror());
}
static char *get_ping_time(char *nick)
{
char *ping_str;
PING *ping, *prev_ping = NULL;
int ping_time;
for (ping = pings; ping; ping = ping->next) {
if (! strcmp(nick, ping->nick))
break;
prev_ping = ping;
}
if (! ping)
return NULL;
if (prev_ping) {
prev_ping->next = ping->next;
} else {
pings = pings->next;
}
ping_time = time(NULL) - ping->start;
ping_str = (char*)malloc(80);
if (ping_time != 1) {
sprintf(ping_str, "%d seconds", ping_time);
} else {
sprintf(ping_str, "%d second", ping_time);
}
free(ping->nick);
free((char*)ping);
return ping_str;
}
void rcv_global(int type, char *data)
{
char *nick, *text, *ptr, *tmp = (char*)malloc(8192);
CHAN *c;
PRIV *p;
char *ping_str;
ptr = strtok(data, " ");
nick = new_string(ptr);
if ((ptr = strtok(NULL, "\0")))
text = new_string(ptr);
else
text = new_string("");
switch (type) {
case MSG_CLIENT_PRIVMSG:
sprintf(tmp, "[%s] %s", nick, text);
put_rcvd(tmp, PRIVMSG_COLOR);
if (priv_nick)
free(priv_nick);
priv_nick = new_string(nick);
play_sound(sound[PRIVMSG_SOUND]);
break;
case MSG_SERVER_WALLOP:
sprintf(tmp, "*** OPERATOR MESSAGE from %s: %s",
nick, text);
put_rcvd(tmp, INFO_COLOR);
break;
case MSG_SERVER_ANNOUNCE:
sprintf(tmp, "*** GLOBAL MESSAGE from %s: %s",
nick, text);
put_rcvd(tmp, INFO_COLOR);
break;
case MSG_SERVER_PING:
sprintf(tmp, "*** %s PING", nick);
put_rcvd(tmp, INFO_COLOR);
strcpy(tmp, nick);
if (send_msg(MSG_CLIENT_PONG, tmp))
disconnect(ws_strerror());
break;
case MSG_SERVER_PONG:
if (! (ping_str = get_ping_time(nick)))
goto end;
sprintf(tmp, "*** PONG received from %s: %s",
nick, ping_str);
put_rcvd(tmp, INFO_COLOR);
free(ping_str);
break;
}
end:
free(tmp);
free(nick);
free(text);
}
void rcv_channel(int type, char *data)
{
char *topic, *channel, *nick, *text, *empty = "";
char *tmp = (char*)malloc(8192);
CHAN *c;
channel = strtok(data, " ");
c = find_chan_by_name(channel);
if (! c)
goto end;
switch (type) {
case MSG_SERVER_PUBLIC:
nick = strtok(NULL, " ");
if (! (text = strtok(NULL, "\0")))
text = empty;
sprintf(tmp, "<%s> %s", nick, text);
put_rcvd(tmp, CHANMSG_COLOR);
play_sound(sound[CHANMSG_SOUND]);
break;
case MSG_SERVER_TOPIC:
if ((topic = strtok(NULL, "\0")))
sprintf(tmp, "%s %s", channel, topic);
else
strcpy(tmp, channel);
tmp[79] = 0;
show_info(tmp);
break;
case MSG_CLIENT_EMOTE:
nick = strtok(NULL, " ");
if (! (text = strtok(NULL, "\"")))
text = empty;
sprintf(tmp, "* %s %s", nick, text);
put_rcvd(tmp, INFO_COLOR);
break;
}
end:
free(tmp);
}
/*
static void ShowQuickInfo(CHAN *c, char *nick)
{
char values[3];
enum {SHARED, LINK, END};
ULIST *ul;
char shared[20], link[20];
for(ul = c->users; ul; ul = ul->next) {
if (! strcmp(ul->nick, nick))
break;
}
sprintf(shared, "%d", ul->shared);
values[SHARED] = shared;
sprintf(link, "%s", linkStr[ul->link]);
values[LINK] = link;
values[END] = NULL;
ShowInfo("quickInfo", values, 15);
}
*/
void join_channel(char *name)
{
if (join_chan)
part_channel(join_chan);
if (send_msg(MSG_CLIENT_JOIN, name))
disconnect(ws_strerror());
}
void do_join_channel(char *name)
{
char tmp[256];
CHAN *ptr, *new_chn;
new_chn = (CHAN*)malloc(sizeof(CHAN));
new_chn->name = new_string(name);
new_chn->users = NULL;
new_chn->next = NULL;
if (! channels)
channels = new_chn;
else {
for (ptr = channels; ptr->next; ptr = ptr->next);
ptr->next = new_chn;
}
if (join_chan)
free(join_chan);
join_chan = new_string(name);
}
void part_channel(char *name)
{
if (send_msg(MSG_CLIENT_PART, name))
disconnect(ws_strerror());
}
void do_part_channel(char *name)
{
CHAN *ptr, *prev_ptr = NULL;
char *p;
for (ptr = channels; ptr; ptr = ptr->next) {
if (! strcmp(ptr->name, name))
break;
prev_ptr = ptr;
}
if (! ptr) {
err_msg("do_part_channel: no such channel");
return;
}
while (ptr->users) {
free(ptr->users->nick);
p = (char*)ptr->users;
ptr->users = ptr->users->next;
free(p);
}
if (prev_ptr) {
prev_ptr->next = ptr->next;
} else {
channels = channels->next;
}
free(ptr->name);
free((char*)ptr);
if (join_chan) {
free(join_chan);
join_chan = NULL;
show_info("");
}
}
void part_all_channels(void)
{
while (channels)
do_part_channel(channels->name);
}
void update_userlist(int type, char *data)
{
char *channel, *nick;
CHAN *ptr;
ULIST *new_user, *user_ptr, *prev_ptr = NULL;
char tmp[256];
int n, shared, link;
channel = strtok(data, " ");
nick = strtok(NULL, " ");
shared = atoi(strtok(NULL, " "));
link = atoi(strtok(NULL, " "));
if (! (ptr = find_chan_by_name(channel))) {
err_msg("update_user_list: channel not found");
return;
}
if ((type == MSG_SERVER_JOIN) ||
(type == MSG_SERVER_CHANNEL_USER_LIST)) {
new_user = (ULIST*)malloc(sizeof(ULIST));
new_user->nick = new_string(nick);
new_user->shared = shared;
new_user->link = link;
if (! ptr->users) {
ptr->users = new_user;
new_user->next = NULL;
n = 1;
} else {
for (user_ptr = ptr->users, n = 1; user_ptr;
user_ptr = user_ptr->next, n++) {
if (strcmp(user_ptr->nick, nick) > 0)
break;
prev_ptr = user_ptr;
}
if (prev_ptr) {
new_user->next = prev_ptr->next;
prev_ptr->next = new_user;
} else {
new_user->next = ptr->users;
ptr->users = new_user;
}
}
if (type == MSG_SERVER_JOIN) {
sprintf(tmp, "*** %s has joined channel %s", nick, channel);
put_rcvd(tmp, JOIN_PART_COLOR);
play_sound(sound[JOIN_SOUND]);
}
} else {
for (user_ptr = ptr->users; user_ptr; user_ptr = user_ptr->next) {
if (! strcmp(user_ptr->nick, nick))
break;
prev_ptr = user_ptr;
}
if (! user_ptr) {
err_msg("update_user_list: no such nick");
return;
}
if (prev_ptr) {
prev_ptr->next = user_ptr->next;
} else {
ptr->users = ptr->users->next;
}
free(user_ptr->nick);
free(user_ptr);
sprintf(tmp, "*** %s has left channel %s", nick, channel);
put_rcvd(tmp, JOIN_PART_COLOR);
play_sound(sound[PART_SOUND]);
}
}
void show_users(char *channel)
{
CHAN *ptr;
ULIST *user_ptr;
char *tmp = malloc(1), tmp2[128];
if (! (ptr = find_chan_by_name(channel))) {
err_msg("show_users: channel not found");
return;
}
*tmp = '\0';
for (user_ptr = ptr->users; user_ptr; user_ptr = user_ptr->next) {
sprintf(tmp2, "%-20.18s", user_ptr->nick);
tmp = realloc(tmp, strlen(tmp) + strlen(tmp2) + 1);
strcat(tmp, tmp2);
}
sprintf(tmp2, "\nUsers on channel %s\n", channel);
put_rcvd(tmp2, JOIN_PART_COLOR);
put_rcvd(tmp, JOIN_PART_COLOR);
put_rcvd("", JOIN_PART_COLOR);
free(tmp);
}