X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fchat.cpp;h=c9317a079dadd73be72c4266e5d2e36a7fb8921f;hb=0f74c7a977c412a81890926548e2a5c8dae5f6eb;hp=cebe312257cc335c1fc21f2ec21992a0a01e1d9d;hpb=2cdd9b4ab6cfc878dafb88aa8446b12cf2f94278;p=dragonfireclient.git diff --git a/src/chat.cpp b/src/chat.cpp index cebe31225..c9317a079 100644 --- a/src/chat.cpp +++ b/src/chat.cpp @@ -18,38 +18,31 @@ with this program; if not, write to the Free Software Foundation, Inc., */ #include "chat.h" -#include "debug.h" -#include "util/strfnd.h" + +#include #include #include + +#include "config.h" +#include "debug.h" +#include "util/strfnd.h" #include "util/string.h" #include "util/numeric.h" ChatBuffer::ChatBuffer(u32 scrollback): - m_scrollback(scrollback), - m_unformatted(), - m_cols(0), - m_rows(0), - m_scroll(0), - m_formatted(), - m_empty_formatted_line() + m_scrollback(scrollback) { if (m_scrollback == 0) m_scrollback = 1; m_empty_formatted_line.first = true; } -ChatBuffer::~ChatBuffer() -{ -} - -void ChatBuffer::addLine(std::wstring name, std::wstring text) +void ChatBuffer::addLine(const std::wstring &name, const std::wstring &text) { ChatLine line(name, text); m_unformatted.push_back(line); - if (m_rows > 0) - { + if (m_rows > 0) { // m_formatted is valid and must be kept valid bool scrolled_at_bottom = (m_scroll == getBottomScrollPos()); u32 num_added = formatChatLine(line, m_cols, m_formatted); @@ -58,8 +51,7 @@ void ChatBuffer::addLine(std::wstring name, std::wstring text) } // Limit number of lines by m_scrollback - if (m_unformatted.size() > m_scrollback) - { + if (m_unformatted.size() > m_scrollback) { deleteOldest(m_unformatted.size() - m_scrollback); } } @@ -76,11 +68,6 @@ u32 ChatBuffer::getLineCount() const return m_unformatted.size(); } -u32 ChatBuffer::getScrollback() const -{ - return m_scrollback; -} - const ChatLine& ChatBuffer::getLine(u32 index) const { assert(index < getLineCount()); // pre-condition @@ -89,9 +76,8 @@ const ChatLine& ChatBuffer::getLine(u32 index) const void ChatBuffer::step(f32 dtime) { - for (u32 i = 0; i < m_unformatted.size(); ++i) - { - m_unformatted[i].age += dtime; + for (ChatLine &line : m_unformatted) { + line.age += dtime; } } @@ -137,14 +123,14 @@ void ChatBuffer::deleteByAge(f32 maxAge) deleteOldest(count); } -u32 ChatBuffer::getColumns() const +u32 ChatBuffer::getRows() const { - return m_cols; + return m_rows; } -u32 ChatBuffer::getRows() const +void ChatBuffer::scrollTop() { - return m_rows; + m_scroll = getTopScrollPos(); } void ChatBuffer::reformat(u32 cols, u32 rows) @@ -208,8 +194,8 @@ const ChatFormattedLine& ChatBuffer::getFormattedLine(u32 row) const s32 index = m_scroll + (s32) row; if (index >= 0 && index < (s32) m_formatted.size()) return m_formatted[index]; - else - return m_empty_formatted_line; + + return m_empty_formatted_line; } void ChatBuffer::scroll(s32 rows) @@ -234,11 +220,6 @@ void ChatBuffer::scrollBottom() m_scroll = getBottomScrollPos(); } -void ChatBuffer::scrollTop() -{ - m_scroll = getTopScrollPos(); -} - u32 ChatBuffer::formatChatLine(const ChatLine& line, u32 cols, std::vector& destination) const { @@ -251,8 +232,7 @@ u32 ChatBuffer::formatChatLine(const ChatLine& line, u32 cols, u32 hanging_indentation = 0; // Format the sender name and produce fragments - if (!line.name.empty()) - { + if (!line.name.empty()) { temp_frag.text = L"<"; temp_frag.column = 0; //temp_frag.bold = 0; @@ -267,22 +247,20 @@ u32 ChatBuffer::formatChatLine(const ChatLine& line, u32 cols, next_frags.push_back(temp_frag); } + std::wstring name_sanitized = line.name.c_str(); + // Choose an indentation level - if (line.name.empty()) - { + if (line.name.empty()) { // Server messages hanging_indentation = 0; - } - else if (line.name.size() + 3 <= cols/2) - { + } else if (name_sanitized.size() + 3 <= cols/2) { // Names shorter than about half the console width hanging_indentation = line.name.size() + 3; - } - else - { + } else { // Very long names hanging_indentation = 2; } + //EnrichedString line_text(line.text); next_line.first = true; bool text_processing = false; @@ -338,7 +316,7 @@ u32 ChatBuffer::formatChatLine(const ChatLine& line, u32 cols, while (frag_length < remaining_in_input && frag_length < remaining_in_output) { - if (isspace(line.text[in_pos + frag_length])) + if (iswspace(line.text.getString()[in_pos + frag_length])) space_pos = frag_length; ++frag_length; } @@ -370,10 +348,11 @@ s32 ChatBuffer::getTopScrollPos() const s32 rows = (s32) m_rows; if (rows == 0) return 0; - else if (formatted_count <= rows) + + if (formatted_count <= rows) return formatted_count - rows; - else - return 0; + + return 0; } s32 ChatBuffer::getBottomScrollPos() const @@ -382,28 +361,21 @@ s32 ChatBuffer::getBottomScrollPos() const s32 rows = (s32) m_rows; if (rows == 0) return 0; - else - return formatted_count - rows; -} - + return formatted_count - rows; +} -ChatPrompt::ChatPrompt(std::wstring prompt, u32 history_limit): - m_prompt(prompt), - m_line(L""), - m_history(), - m_history_index(0), - m_history_limit(history_limit), - m_cols(0), - m_view(0), - m_cursor(0), - m_cursor_len(0), - m_nick_completion_start(0), - m_nick_completion_end(0) +void ChatBuffer::resize(u32 scrollback) { + m_scrollback = scrollback; + if (m_unformatted.size() > m_scrollback) + deleteOldest(m_unformatted.size() - m_scrollback); } -ChatPrompt::~ChatPrompt() + +ChatPrompt::ChatPrompt(const std::wstring &prompt, u32 history_limit): + m_prompt(prompt), + m_history_limit(history_limit) { } @@ -425,10 +397,16 @@ void ChatPrompt::input(const std::wstring &str) m_nick_completion_end = 0; } -void ChatPrompt::addToHistory(std::wstring line) +void ChatPrompt::addToHistory(const std::wstring &line) { - if (!line.empty()) + if (!line.empty() && + (m_history.size() == 0 || m_history.back() != line)) { + // Remove all duplicates + m_history.erase(std::remove(m_history.begin(), m_history.end(), + line), m_history.end()); + // Push unique line m_history.push_back(line); + } if (m_history.size() > m_history_limit) m_history.erase(m_history.begin()); m_history_index = m_history.size(); @@ -443,7 +421,7 @@ void ChatPrompt::clear() m_nick_completion_end = 0; } -std::wstring ChatPrompt::replace(std::wstring line) +std::wstring ChatPrompt::replace(const std::wstring &line) { std::wstring old_line = m_line; m_line = line; @@ -495,9 +473,9 @@ void ChatPrompt::nickCompletion(const std::list& names, bool backwa { // no previous nick completion is active prefix_start = prefix_end = m_cursor; - while (prefix_start > 0 && !isspace(m_line[prefix_start-1])) + while (prefix_start > 0 && !iswspace(m_line[prefix_start-1])) --prefix_start; - while (prefix_end < m_line.size() && !isspace(m_line[prefix_end])) + while (prefix_end < m_line.size() && !iswspace(m_line[prefix_end])) ++prefix_end; if (prefix_start == prefix_end) return; @@ -506,18 +484,15 @@ void ChatPrompt::nickCompletion(const std::list& names, bool backwa // find all names that start with the selected prefix std::vector completions; - for (std::list::const_iterator - i = names.begin(); - i != names.end(); ++i) - { - if (str_starts_with(narrow_to_wide(*i), prefix, true)) - { - std::wstring completion = narrow_to_wide(*i); + for (const std::string &name : names) { + std::wstring completion = utf8_to_wide(name); + if (str_starts_with(completion, prefix, true)) { if (prefix_start == 0) completion += L": "; completions.push_back(completion); } } + if (completions.empty()) return; @@ -526,7 +501,7 @@ void ChatPrompt::nickCompletion(const std::list& names, bool backwa u32 replacement_index = 0; if (!initial) { - while (word_end < m_line.size() && !isspace(m_line[word_end])) + while (word_end < m_line.size() && !iswspace(m_line[word_end])) ++word_end; std::wstring word = m_line.substr(prefix_start, word_end - prefix_start); @@ -545,7 +520,7 @@ void ChatPrompt::nickCompletion(const std::list& names, bool backwa } } std::wstring replacement = completions[replacement_index]; - if (word_end < m_line.size() && isspace(word_end)) + if (word_end < m_line.size() && iswspace(m_line[word_end])) ++word_end; // replace existing word with replacement word, @@ -600,17 +575,17 @@ void ChatPrompt::cursorOperation(CursorOp op, CursorOpDir dir, CursorOpScope sco case CURSOROP_SCOPE_WORD: if (dir == CURSOROP_DIR_RIGHT) { // skip one word to the right - while (new_cursor < length && isspace(m_line[new_cursor])) + while (new_cursor < length && iswspace(m_line[new_cursor])) new_cursor++; - while (new_cursor < length && !isspace(m_line[new_cursor])) + while (new_cursor < length && !iswspace(m_line[new_cursor])) new_cursor++; - while (new_cursor < length && isspace(m_line[new_cursor])) + while (new_cursor < length && iswspace(m_line[new_cursor])) new_cursor++; } else { // skip one word to the left - while (new_cursor >= 1 && isspace(m_line[new_cursor - 1])) + while (new_cursor >= 1 && iswspace(m_line[new_cursor - 1])) new_cursor--; - while (new_cursor >= 1 && !isspace(m_line[new_cursor - 1])) + while (new_cursor >= 1 && !iswspace(m_line[new_cursor - 1])) new_cursor--; } break; @@ -680,16 +655,10 @@ ChatBackend::ChatBackend(): { } -ChatBackend::~ChatBackend() -{ -} - -void ChatBackend::addMessage(std::wstring name, std::wstring text) +void ChatBackend::addMessage(const std::wstring &name, std::wstring text) { - name = unescape_enriched(name); - text = unescape_enriched(text); - // Note: A message may consist of multiple lines, for example the MOTD. + text = translate_string(text); WStrfnd fnd(text); while (!fnd.at_end()) { @@ -732,19 +701,21 @@ ChatBuffer& ChatBackend::getRecentBuffer() return m_recent_buffer; } -std::wstring ChatBackend::getRecentChat() +EnrichedString ChatBackend::getRecentChat() const { - std::wostringstream stream; - for (u32 i = 0; i < m_recent_buffer.getLineCount(); ++i) - { + EnrichedString result; + for (u32 i = 0; i < m_recent_buffer.getLineCount(); ++i) { const ChatLine& line = m_recent_buffer.getLine(i); if (i != 0) - stream << L"\n"; - if (!line.name.empty()) - stream << L"<" << line.name << L"> "; - stream << line.text; + result += L"\n"; + if (!line.name.empty()) { + result += L"<"; + result += line.name; + result += L"> "; + } + result += line.text; } - return stream.str(); + return result; } ChatPrompt& ChatBackend::getPrompt() @@ -767,6 +738,14 @@ void ChatBackend::clearRecentChat() m_recent_buffer.clear(); } + +void ChatBackend::applySettings() +{ + u32 recent_lines = g_settings->getU32("recent_chat_messages"); + recent_lines = rangelim(recent_lines, 2, 20); + m_recent_buffer.resize(recent_lines); +} + void ChatBackend::step(float dtime) { m_recent_buffer.step(dtime);