]> git.lizzy.rs Git - dragonfireclient.git/blobdiff - src/chat.cpp
Hard-coded undersampling.
[dragonfireclient.git] / src / chat.cpp
index 2d29d39da77fe1b87381607b392ee920a7732e45..46555b3dcc8f9da920efa2c44cade7e7ca971d6a 100644 (file)
@@ -19,7 +19,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 
 #include "chat.h"
 #include "debug.h"
-#include "strfnd.h"
+#include "config.h"
+#include "util/strfnd.h"
 #include <cctype>
 #include <sstream>
 #include "util/string.h"
@@ -97,6 +98,8 @@ void ChatBuffer::step(f32 dtime)
 
 void ChatBuffer::deleteOldest(u32 count)
 {
+       bool at_bottom = (m_scroll == getBottomScrollPos());
+
        u32 del_unformatted = 0;
        u32 del_formatted = 0;
 
@@ -120,6 +123,11 @@ void ChatBuffer::deleteOldest(u32 count)
 
        m_unformatted.erase(m_unformatted.begin(), m_unformatted.begin() + del_unformatted);
        m_formatted.erase(m_formatted.begin(), m_formatted.begin() + del_formatted);
+
+       if (at_bottom)
+               m_scroll = getBottomScrollPos();
+       else
+               scrollAbsolute(m_scroll - del_formatted);
 }
 
 void ChatBuffer::deleteByAge(f32 maxAge)
@@ -244,8 +252,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;
@@ -260,22 +267,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;
@@ -331,7 +336,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 (isspace(line.text.getString()[in_pos + frag_length]))
                                        space_pos = frag_length;
                                ++frag_length;
                        }
@@ -390,6 +395,7 @@ ChatPrompt::ChatPrompt(std::wstring prompt, u32 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)
 {
@@ -417,20 +423,13 @@ void ChatPrompt::input(const std::wstring &str)
        m_nick_completion_end = 0;
 }
 
-std::wstring ChatPrompt::submit()
+void ChatPrompt::addToHistory(std::wstring line)
 {
-       std::wstring line = m_line;
-       m_line.clear();
        if (!line.empty())
                m_history.push_back(line);
        if (m_history.size() > m_history_limit)
                m_history.erase(m_history.begin());
        m_history_index = m_history.size();
-       m_view = 0;
-       m_cursor = 0;
-       m_nick_completion_start = 0;
-       m_nick_completion_end = 0;
-       return line;
 }
 
 void ChatPrompt::clear()
@@ -442,13 +441,15 @@ void ChatPrompt::clear()
        m_nick_completion_end = 0;
 }
 
-void ChatPrompt::replace(std::wstring line)
+std::wstring ChatPrompt::replace(std::wstring line)
 {
+       std::wstring old_line = m_line;
        m_line =  line;
        m_view = m_cursor = line.size();
        clampView();
        m_nick_completion_start = 0;
        m_nick_completion_end = 0;
+       return old_line;
 }
 
 void ChatPrompt::historyPrev()
@@ -511,7 +512,7 @@ void ChatPrompt::nickCompletion(const std::list<std::string>& names, bool backwa
                {
                        std::wstring completion = narrow_to_wide(*i);
                        if (prefix_start == 0)
-                               completion += L":";
+                               completion += L": ";
                        completions.push_back(completion);
                }
        }
@@ -541,7 +542,7 @@ void ChatPrompt::nickCompletion(const std::list<std::string>& names, bool backwa
                        }
                }
        }
-       std::wstring replacement = completions[replacement_index] + L" ";
+       std::wstring replacement = completions[replacement_index];
        if (word_end < m_line.size() && isspace(word_end))
                ++word_end;
 
@@ -590,14 +591,12 @@ void ChatPrompt::cursorOperation(CursorOp op, CursorOpDir dir, CursorOpScope sco
        s32 length = m_line.size();
        s32 increment = (dir == CURSOROP_DIR_RIGHT) ? 1 : -1;
 
-       if (scope == CURSOROP_SCOPE_CHARACTER)
-       {
+       switch (scope) {
+       case CURSOROP_SCOPE_CHARACTER:
                new_cursor += increment;
-       }
-       else if (scope == CURSOROP_SCOPE_WORD)
-       {
-               if (increment > 0)
-               {
+               break;
+       case CURSOROP_SCOPE_WORD:
+               if (dir == CURSOROP_DIR_RIGHT) {
                        // skip one word to the right
                        while (new_cursor < length && isspace(m_line[new_cursor]))
                                new_cursor++;
@@ -605,39 +604,47 @@ void ChatPrompt::cursorOperation(CursorOp op, CursorOpDir dir, CursorOpScope sco
                                new_cursor++;
                        while (new_cursor < length && isspace(m_line[new_cursor]))
                                new_cursor++;
-               }
-               else
-               {
+               } else {
                        // skip one word to the left
                        while (new_cursor >= 1 && isspace(m_line[new_cursor - 1]))
                                new_cursor--;
                        while (new_cursor >= 1 && !isspace(m_line[new_cursor - 1]))
                                new_cursor--;
                }
-       }
-       else if (scope == CURSOROP_SCOPE_LINE)
-       {
+               break;
+       case CURSOROP_SCOPE_LINE:
                new_cursor += increment * length;
+               break;
+       case CURSOROP_SCOPE_SELECTION:
+               break;
        }
 
        new_cursor = MYMAX(MYMIN(new_cursor, length), 0);
 
-       if (op == CURSOROP_MOVE)
-       {
+       switch (op) {
+       case CURSOROP_MOVE:
                m_cursor = new_cursor;
-       }
-       else if (op == CURSOROP_DELETE)
-       {
-               if (new_cursor < old_cursor)
-               {
-                       m_line.erase(new_cursor, old_cursor - new_cursor);
-                       m_cursor = new_cursor;
+               m_cursor_len = 0;
+               break;
+       case CURSOROP_DELETE:
+               if (m_cursor_len > 0) { // Delete selected text first
+                       m_line.erase(m_cursor, m_cursor_len);
+               } else {
+                       m_cursor = MYMIN(new_cursor, old_cursor);
+                       m_line.erase(m_cursor, abs(new_cursor - old_cursor));
                }
-               else if (new_cursor > old_cursor)
-               {
-                       m_line.erase(old_cursor, new_cursor - old_cursor);
-                       m_cursor = old_cursor;
+               m_cursor_len = 0;
+               break;
+       case CURSOROP_SELECT:
+               if (scope == CURSOROP_SCOPE_LINE) {
+                       m_cursor = 0;
+                       m_cursor_len = length;
+               } else {
+                       m_cursor = MYMIN(new_cursor, old_cursor);
+                       m_cursor_len += abs(new_cursor - old_cursor);
+                       m_cursor_len = MYMIN(m_cursor_len, length - m_cursor);
                }
+               break;
        }
 
        clampView();
@@ -679,7 +686,7 @@ void ChatBackend::addMessage(std::wstring name, std::wstring text)
 {
        // Note: A message may consist of multiple lines, for example the MOTD.
        WStrfnd fnd(text);
-       while (!fnd.atend())
+       while (!fnd.at_end())
        {
                std::wstring line = fnd.next(L"\n");
                m_console_buffer.addLine(name, line);
@@ -720,19 +727,22 @@ ChatBuffer& ChatBackend::getRecentBuffer()
        return m_recent_buffer;
 }
 
-std::wstring ChatBackend::getRecentChat()
+EnrichedString ChatBackend::getRecentChat()
 {
-       std::wostringstream stream;
+       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()