/* libobby - Network text editing library
* Copyright (C) 2005 0x539 dev group
*
* 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; either
* version 2 of the License, or (at your option) any later version.
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "format_string.hpp"
#include "common.hpp"
#include "chat.hpp"
namespace
{
// Discards old messages
void discard_messages(std::list<obby::chat::message*>& list,
unsigned int max)
{
while(list.size() > max)
{
delete list.front();
list.pop_front();
}
}
}
obby::chat::message::message(const std::string& text,
std::time_t timestamp):
m_text(text), m_timestamp(timestamp)
{
}
obby::chat::message::message(const serialise::object& obj,
const user_table& user_table):
m_text(obj.get_required_attribute("text").get_value() ),
m_timestamp(obj.get_required_attribute("timestamp").as<std::time_t>() )
{
}
obby::chat::message::~message()
{
}
void obby::chat::message::serialise(serialise::object& obj) const
{
obj.add_attribute("text").set_value(m_text);
obj.add_attribute("timestamp").set_value(m_timestamp);
}
const std::string& obby::chat::message::get_text() const
{
return m_text;
}
std::time_t obby::chat::message::get_timestamp() const
{
return m_timestamp;
}
std::string obby::chat::message::format_timestamp(const char* format) const
{
std::size_t alloc_size = 64;
char* buf = static_cast<char*>(std::malloc(alloc_size) );
std::tm* tm = std::localtime(&m_timestamp);
for(;;)
{
std::size_t retval = std::strftime(buf, alloc_size, format, tm);
if(retval == 0 || retval == alloc_size)
{
buf = static_cast<char*>(
std::realloc(buf, alloc_size *= 2)
);
}
else
break;
}
std::string result = buf;
std::free(buf);
return result;
}
obby::chat::user_message::user_message(const std::string& text,
std::time_t timestamp,
const user& from):
message(text, timestamp), m_user(from)
{
}
obby::chat::user_message::user_message(const serialise::object& obj,
const user_table& user_table):
message(obj, user_table),
m_user(
*obj.get_required_attribute("user").as<const user*>(
::serialise::default_context_from<const user*>(
user_table
)
)
)
{
}
void obby::chat::user_message::serialise(serialise::object& obj) const
{
message::serialise(obj);
obj.add_attribute("user").set_value(&m_user);
}
const obby::user& obby::chat::user_message::get_user() const
{
return m_user;
}
std::string obby::chat::user_message::repr() const
{
format_string str("<%0%> %1%");
str << m_user.get_name() << m_text;
return str.str();
}
obby::chat::emote_message::emote_message(const std::string& text,
std::time_t timestamp,
const user& from):
user_message(text, timestamp, from)
{
}
obby::chat::emote_message::emote_message(const serialise::object& obj,
const user_table& user_table):
user_message(obj, user_table)
{
}
std::string obby::chat::emote_message::repr() const
{
format_string str(" * %0% %1%");
str << m_user.get_name() << m_text;
return str.str();
}
obby::chat::server_message::server_message(const std::string& text,
std::time_t timestamp):
message(text, timestamp)
{
}
obby::chat::server_message::server_message(const serialise::object& obj,
const user_table& user_table):
message(obj, user_table)
{
}
std::string obby::chat::server_message::repr() const
{
return m_text;
}
obby::chat::system_message::system_message(const std::string& text,
std::time_t timestamp):
message(text, timestamp)
{
}
obby::chat::system_message::system_message(const serialise::object& obj,
const user_table& user_table):
message(obj, user_table)
{
}
std::string obby::chat::system_message::repr() const
{
return m_text;
}
/*obby::chat::chat(unsigned int max_messages):
m_max_messages(max_messages)
{
}*/
obby::chat::~chat()
{
clear();
}
void obby::chat::serialise(serialise::object& obj) const
{
for(message_iterator iter = message_begin();
iter != message_end();
++ iter)
{
message* msg = &(*iter);
serialise::object& child = obj.add_child();
// Set child name according to message type
// TODO: virtual call that gets this string
if(dynamic_cast<emote_message*>(msg) != NULL)
child.set_name("emote_message");
else if(dynamic_cast<user_message*>(msg) != NULL)
child.set_name("user_message");
else if(dynamic_cast<server_message*>(msg) != NULL)
child.set_name("server_message");
else if(dynamic_cast<system_message*>(msg) != NULL)
child.set_name("system_message");
else
throw std::logic_error("obby::chat::serialise");
iter->serialise(child);
}
}
void obby::chat::deserialise(const serialise::object& obj,
const user_table& user_table)
{
clear();
for(serialise::object::child_iterator iter = obj.children_begin();
iter != obj.children_end();
++ iter)
{
if(iter->get_name() == "emote_message")
{
add_message(new emote_message(*iter, user_table) );
}
else if(iter->get_name() == "user_message")
{
add_message(new user_message(*iter, user_table) );
}
else if(iter->get_name() == "server_message")
{
add_message(new server_message(*iter, user_table) );
}
else if(iter->get_name() == "system_message")
{
add_message(new system_message(*iter, user_table) );
}
else
{
// TODO: Unexpected child error
format_string str(_("Unexpected child node: '%0%'") );
str << iter->get_name();
throw serialise::error(str.str(), iter->get_line() );
}
}
add_message(new system_message(_("Restored session"), std::time(NULL)));
}
void obby::chat::clear()
{
for(std::list<message*>::iterator iter = m_messages.begin();
iter != m_messages.end();
++ iter)
{
delete *iter;
}
m_messages.clear();
}
void obby::chat::add_user_message(const std::string& text,
const user& from)
{
add_message(new user_message(text, std::time(NULL), from) );
}
void obby::chat::add_emote_message(const std::string& text,
const user& from)
{
add_message(new emote_message(text, std::time(NULL), from) );
}
void obby::chat::add_server_message(const std::string& text)
{
add_message(new server_message(text, std::time(NULL)) );
}
obby::chat::message_iterator obby::chat::message_begin() const
{
return m_messages.begin();
}
obby::chat::message_iterator obby::chat::message_end() const
{
return m_messages.end();
}
obby::chat::signal_message_type obby::chat::message_event() const
{
return m_signal_message;
}
void obby::chat::add_message(message* msg)
{
m_messages.push_back(msg);
discard_messages(m_messages, m_max_messages);
m_signal_message.emit(*msg);
}
void obby::chat::on_sync_init(unsigned int)
{
m_user_join_conn.block();
m_user_part_conn.block();
m_document_insert_conn.block();
m_document_remove_conn.block();
}
void obby::chat::on_sync_final()
{
m_user_join_conn.unblock();
m_user_part_conn.unblock();
m_document_insert_conn.unblock();
m_document_remove_conn.unblock();
}
void obby::chat::on_user_join(const user& user)
{
if(~user.get_flags() & user::flags::CONNECTED)
return;
obby::format_string str(_("%0% has joined") );
str << user.get_name();
add_message(new system_message(str.str(), std::time(NULL)) );
}
void obby::chat::on_user_part(const user& user)
{
obby::format_string str(_("%0% has left") );
str << user.get_name();
add_message(new system_message(str.str(), std::time(NULL)) );
}
syntax highlighted by Code2HTML, v. 0.9.1