diff options
Diffstat (limited to 'src/chat.cpp')
-rw-r--r-- | src/chat.cpp | 148 |
1 files changed, 132 insertions, 16 deletions
diff --git a/src/chat.cpp b/src/chat.cpp index c9317a079..9bceb3535 100644 --- a/src/chat.cpp +++ b/src/chat.cpp @@ -35,6 +35,25 @@ ChatBuffer::ChatBuffer(u32 scrollback): if (m_scrollback == 0) m_scrollback = 1; m_empty_formatted_line.first = true; + + // Curses mode cannot access g_settings here + if(g_settings != NULL) + { + m_cache_clickable_chat_weblinks = g_settings->getBool("clickable_chat_weblinks"); + if(m_cache_clickable_chat_weblinks) + { + std::string hexcode = g_settings->get("chat_weblink_color"); + u32 colorval = strtol(hexcode.c_str(), NULL, 16); + u32 redval,greenval,blueval; + blueval = colorval % 256; + colorval /= 256; + greenval = colorval % 256; + colorval /= 256; + redval = colorval % 256; + // discard alpha, if included + m_cache_chat_weblink_color = irr::video::SColor(255,redval,greenval,blueval); + } + } } void ChatBuffer::addLine(const std::wstring &name, const std::wstring &text) @@ -272,6 +291,11 @@ u32 ChatBuffer::formatChatLine(const ChatLine& line, u32 cols, while (!next_frags.empty()) { ChatFormattedFragment& frag = next_frags[0]; + + // Force text_processing on this frag. hacky. + if(frag.column == u32(INT_MAX)) + text_processing = true; + if (frag.text.size() <= cols - out_column) { // Fragment fits into current line @@ -286,9 +310,11 @@ u32 ChatBuffer::formatChatLine(const ChatLine& line, u32 cols, // So split it up temp_frag.text = frag.text.substr(0, cols - out_column); temp_frag.column = out_column; - //temp_frag.bold = frag.bold; + temp_frag.meta = frag.meta; + next_line.fragments.push_back(temp_frag); frag.text = frag.text.substr(cols - out_column); + frag.column = 0; out_column = cols; } if (out_column == cols || text_processing) @@ -300,10 +326,11 @@ u32 ChatBuffer::formatChatLine(const ChatLine& line, u32 cols, next_line.first = false; out_column = text_processing ? hanging_indentation : 0; + text_processing = false; } } - // Produce fragment + // Produce fragment(s) for next formatted line if (in_pos < line.text.size()) { u32 remaining_in_input = line.text.size() - in_pos; @@ -313,22 +340,111 @@ u32 ChatBuffer::formatChatLine(const ChatLine& line, u32 cols, // remaining_in_{in,out}put. Try to end the fragment // on a word boundary. u32 frag_length = 1, space_pos = 0; - while (frag_length < remaining_in_input && - frag_length < remaining_in_output) + + if(!m_cache_clickable_chat_weblinks) + { + while (frag_length < remaining_in_input && + frag_length < remaining_in_output) + { + if (iswspace(line.text.getString()[in_pos + frag_length])) + space_pos = frag_length; + ++frag_length; + } + if (space_pos != 0 && frag_length < remaining_in_input) + frag_length = space_pos + 1; + + temp_frag.text = line.text.substr(in_pos, frag_length); + temp_frag.column = 0; + //temp_frag.bold = 0; + next_frags.push_back(temp_frag); + in_pos += frag_length; + text_processing = true; + } + // Unless weblinks are enabled. Then it's slightly more complex + else { - if (iswspace(line.text.getString()[in_pos + frag_length])) - space_pos = frag_length; - ++frag_length; + u32 http_pos = u32(std::wstring::npos); + text_processing = false; // set FALSE at end of this block + bool halt_fragloop = false; + while(!halt_fragloop) + { + remaining_in_input = line.text.size() - in_pos; + frag_length = 0; + space_pos = 0; + + // Note: unsigned(-1) on fail + http_pos = u32(line.text.getString().find(L"https://", std::size_t(in_pos))); + if(http_pos == u32(std::wstring::npos)) + http_pos = u32(line.text.getString().find(L"http://", std::size_t(in_pos))); + if(http_pos != u32(std::wstring::npos)) + http_pos -= in_pos; + + while (frag_length < remaining_in_input && + frag_length < remaining_in_output) + { + if (iswspace(line.text.getString()[in_pos + frag_length])) + space_pos = frag_length; + ++frag_length; + } + + // Http not in range, grab until space or EOL, halt as normal. + if(http_pos > remaining_in_output) // sufficient unless screen is infinitely wide + { + halt_fragloop = true; + // force text processing on THIS frag + text_processing = true; + } + // At http, grab ALL until FIRST whitespace or quote mark. loop. + // If at end of string, next loop will be empty string to mark end of weblink. This is intentional. + else if(http_pos == 0) + { + frag_length = 6; + while (frag_length < remaining_in_input && + !iswspace(line.text.getString()[in_pos + frag_length]) && + line.text.getString()[in_pos + frag_length] != L'\'' && + line.text.getString()[in_pos + frag_length] != L'\"' && + line.text.getString()[in_pos + frag_length] != L';' + ) + { + ++frag_length; + } + space_pos = frag_length - 1; + if(frag_length >= remaining_in_output) + { + // Force text processing on THIS frag + text_processing = true; + halt_fragloop = true; + } + } + // Http in range, grab until http, loop + else + { + space_pos = http_pos - 1; + frag_length = http_pos; + } + + if (space_pos != 0 && frag_length < remaining_in_input) + frag_length = space_pos + 1; + + temp_frag.text = line.text.substr(in_pos, frag_length); + temp_frag.column = text_processing ? u32(INT_MAX) : 0; + if(http_pos == 0) + { + temp_frag.meta = wide_to_utf8(temp_frag.text.getString()); + temp_frag.text = EnrichedString(temp_frag.text.getString()); + temp_frag.text.setDefaultColor(m_cache_chat_weblink_color); + } + else + { + temp_frag.meta = ""; + } + next_frags.push_back(temp_frag); + in_pos += frag_length; + remaining_in_output -= std::min(frag_length, remaining_in_output); + } + // handled for fragments individually + text_processing = false; } - if (space_pos != 0 && frag_length < remaining_in_input) - frag_length = space_pos + 1; - - temp_frag.text = line.text.substr(in_pos, frag_length); - temp_frag.column = 0; - //temp_frag.bold = 0; - next_frags.push_back(temp_frag); - in_pos += frag_length; - text_processing = true; } } |