From b6c8761e108eade0d1451580fbacf1e3d3f6a957 Mon Sep 17 00:00:00 2001 From: pecksin Date: Thu, 18 Mar 2021 16:47:36 -0400 Subject: re-apply everything manually because git --- minetest.conf.example | 8 ++ po/minetest.pot | 8 ++ src/chat.cpp | 213 +++++++++++++++++++++++++++++++++++++++++---- src/chat.h | 12 +++ src/defaultsettings.cpp | 2 + src/gui/guiChatConsole.cpp | 32 ++++++- src/gui/guiChatConsole.h | 3 + 7 files changed, 261 insertions(+), 17 deletions(-) diff --git a/minetest.conf.example b/minetest.conf.example index f5f608adf..814e34e43 100644 --- a/minetest.conf.example +++ b/minetest.conf.example @@ -16,6 +16,14 @@ # Controls # +# If enabled, http links in chat can be middle-clicked or ctrl-left-clicked to open the link in the OS's default web browser. +# type: bool +# clickable_chat_weblinks = false + +# If clickable_chat_weblinks is enabled, specify the color (as 24-bit hexadecimal) of weblinks in chat. +# type: string +# chat_weblink_color = 8888FF + # If enabled, you can place blocks at the position (feet + eye level) where you stand. # This is helpful when working with nodeboxes in small areas. # type: bool diff --git a/po/minetest.pot b/po/minetest.pot index fedfbc75d..6f527022b 100644 --- a/po/minetest.pot +++ b/po/minetest.pot @@ -6356,3 +6356,11 @@ msgid "" "be queued.\n" "This should be lower than curl_parallel_limit." msgstr "" + +#: src/chat.cpp +msgid "Opening webpage" +msgstr "" + +#: src/chat.cpp +msgid "Failed to open webpage" +msgstr "" diff --git a/src/chat.cpp b/src/chat.cpp index c9317a079..7d8a3903f 100644 --- a/src/chat.cpp +++ b/src/chat.cpp @@ -28,6 +28,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "util/strfnd.h" #include "util/string.h" #include "util/numeric.h" +#include "porting.h" ChatBuffer::ChatBuffer(u32 scrollback): m_scrollback(scrollback) @@ -35,6 +36,21 @@ ChatBuffer::ChatBuffer(u32 scrollback): if (m_scrollback == 0) m_scrollback = 1; m_empty_formatted_line.first = true; + 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,150,150,255); + 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 +288,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 +307,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 +323,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 +337,123 @@ 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; // - in_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()); + // FIXME: this is probably overkill to recolor the link text. + 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); + + /* + std::cout << "----------" << std::endl; + std::cout << "http_pos = " << http_pos << std::endl; + std::cout << "space_pos = " << space_pos << std::endl; + std::cout << "frag: '" << temp_frag.text.size() << "'" << std::endl; + std::cout << "in_pos: '" << in_pos << std::endl; + std::cout << "remain: '" << line.text.substr(in_pos).size() << "'" << std::endl; + std::cout << "remn in in: '" << remaining_in_input << "'" << std::endl; + std::cout << "remn in out: '" << remaining_in_output << "'" << std::endl; + */ + } + // 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; } } @@ -768,3 +893,59 @@ void ChatBackend::scrollPageUp() { m_console_buffer.scroll(-(s32)m_console_buffer.getRows()); } + +void ChatBackend::middleClick(s32 col, s32 row) +{ + // Prevent accidental rapid clicking + static u32 oldtime = 0; + // seriously.. + u32 newtime = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); + + // 0.6 seconds should suffice + if(newtime - oldtime < 600) + return; + oldtime = newtime; + + const std::vector & frags = getConsoleBuffer().getFormattedLine(row).fragments; + std::string weblink = ""; // from frag meta + + // Identify targetted fragment, if exists + int ind = frags.size() - 1; + while(u32(col - 1) < frags[ind].column) + { + --ind; + } + if(ind > -1) + { + weblink = frags[ind].meta; + } + + // Debug help + std::string ws; + ws = "Middleclick: (" + std::to_string(col) + ',' + std::to_string(row) + ')' + " frags:"; + for(u32 i=0;i& destination) const; void resize(u32 scrollback); + protected: s32 getTopScrollPos() const; s32 getBottomScrollPos() const; @@ -138,6 +141,11 @@ private: std::vector m_formatted; // Empty formatted line, for error returns ChatFormattedLine m_empty_formatted_line; + + // Enable clickable chat weblinks + bool m_cache_clickable_chat_weblinks; + // Color of clickable chat weblinks + irr::video::SColor m_cache_chat_weblink_color; }; class ChatPrompt @@ -281,6 +289,10 @@ public: void scrollPageDown(); void scrollPageUp(); + // Handle middle click at this font position + // If clicked fragment has a web url, send it to the system default web browser + void middleClick(s32 col, s32 row); + // Resize recent buffer based on settings void applySettings(); diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index 41c4922a4..c59b93e88 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -282,6 +282,8 @@ void set_default_settings() settings->setDefault("repeat_joystick_button_time", "0.17"); settings->setDefault("joystick_frustum_sensitivity", "170"); settings->setDefault("joystick_deadzone", "2048"); + settings->setDefault("clickable_chat_weblinks", "false"); + settings->setDefault("chat_weblink_color", "8888FF"); // Main menu settings->setDefault("main_menu_path", ""); diff --git a/src/gui/guiChatConsole.cpp b/src/gui/guiChatConsole.cpp index ef471106d..f5336e3ad 100644 --- a/src/gui/guiChatConsole.cpp +++ b/src/gui/guiChatConsole.cpp @@ -90,6 +90,8 @@ GUIChatConsole::GUIChatConsole( // set default cursor options setCursor(true, true, 2.0, 0.1); + + m_cache_clickable_chat_weblinks = g_settings->getBool("clickable_chat_weblinks"); } GUIChatConsole::~GUIChatConsole() @@ -321,6 +323,7 @@ void GUIChatConsole::drawText() #if USE_FREETYPE if (m_font->getType() == irr::gui::EGFT_CUSTOM) { + // Draw colored text if FreeType is enabled irr::gui::CGUITTFont *tmp = dynamic_cast(m_font); tmp->draw( @@ -404,9 +407,24 @@ bool GUIChatConsole::OnEvent(const SEvent& event) { ChatPrompt &prompt = m_chat_backend->getPrompt(); + static bool isctrldown; // track this for mouse event - if(event.EventType == EET_KEY_INPUT_EVENT && event.KeyInput.PressedDown) + if(event.EventType == EET_KEY_INPUT_EVENT && !event.KeyInput.PressedDown) { + // CTRL up + if(event.KeyInput.Key == KEY_LCONTROL || event.KeyInput.Key == KEY_RCONTROL || !event.KeyInput.Control) + { + isctrldown = false; + } + } + else if(event.EventType == EET_KEY_INPUT_EVENT && event.KeyInput.PressedDown) + { + // CTRL down + if(event.KeyInput.Key == KEY_LCONTROL || event.KeyInput.Key == KEY_RCONTROL || event.KeyInput.Control) + { + isctrldown = true; + } + // Key input if (KeyPress(event.KeyInput) == getKeySetting("keymap_console")) { closeConsole(); @@ -624,6 +642,18 @@ bool GUIChatConsole::OnEvent(const SEvent& event) s32 rows = myround(-3.0 * event.MouseInput.Wheel); m_chat_backend->scroll(rows); } + // Middle click opens weblink, if enabled in config + else if(m_cache_clickable_chat_weblinks && ( + event.MouseInput.Event == EMIE_MMOUSE_PRESSED_DOWN || + (event.MouseInput.Event == EMIE_LMOUSE_PRESSED_DOWN && isctrldown) + )) + { + // because console prompt and hardcoded margins + if(event.MouseInput.Y / m_fontsize.Y < (m_height / m_fontsize.Y) - 1 ) + { + m_chat_backend->middleClick(event.MouseInput.X / m_fontsize.X, event.MouseInput.Y / m_fontsize.Y); + } + } } return Parent ? Parent->OnEvent(event) : false; diff --git a/src/gui/guiChatConsole.h b/src/gui/guiChatConsole.h index 896342ab0..501bf50cb 100644 --- a/src/gui/guiChatConsole.h +++ b/src/gui/guiChatConsole.h @@ -124,4 +124,7 @@ private: // font gui::IGUIFont *m_font = nullptr; v2u32 m_fontsize; + + // Enable clickable chat weblinks + bool m_cache_clickable_chat_weblinks; }; -- cgit v1.2.3 From 038a317c213db41227beaa014100dc43b46e392c Mon Sep 17 00:00:00 2001 From: pecksin Date: Fri, 19 Mar 2021 16:25:44 -0400 Subject: user-configurable 'ctrl' keys for ctrl-leftclick in chat weblinks --- minetest.conf.example | 4 +++ src/client/keycode.cpp | 9 +++++++ src/client/keycode.h | 3 +++ src/defaultsettings.cpp | 1 + src/gui/guiChatConsole.cpp | 67 +++++++++++++++++++++++++++++++++++++++++++--- src/gui/guiChatConsole.h | 6 +++++ 6 files changed, 87 insertions(+), 3 deletions(-) diff --git a/minetest.conf.example b/minetest.conf.example index 814e34e43..524ef6334 100644 --- a/minetest.conf.example +++ b/minetest.conf.example @@ -24,6 +24,10 @@ # type: string # chat_weblink_color = 8888FF +# If clickable_chat_weblinks is enabled, specify the keys held down to treat left-click as middle-click. +# type: string (comma-delimited) +# chat_weblink_ctrl_keys = KEY_LCONTROL,KEY_RCONTROL,KEY_CONTROL + # If enabled, you can place blocks at the position (feet + eye level) where you stand. # This is helpful when working with nodeboxes in small areas. # type: bool diff --git a/src/client/keycode.cpp b/src/client/keycode.cpp index ce5214f54..08aff43ce 100644 --- a/src/client/keycode.cpp +++ b/src/client/keycode.cpp @@ -386,3 +386,12 @@ irr::EKEY_CODE keyname_to_keycode(const char *name) { return lookup_keyname(name).Key; } + +irr::EKEY_CODE keyname_to_keycode_safemode(const char *name) +{ + try { + return lookup_keyname(name).Key; + } catch (UnknownKeycode &e) { + return irr::KEY_KEY_CODES_COUNT; + } +} diff --git a/src/client/keycode.h b/src/client/keycode.h index 7036705d1..cb3114099 100644 --- a/src/client/keycode.h +++ b/src/client/keycode.h @@ -65,3 +65,6 @@ KeyPress getKeySetting(const char *settingname); void clearKeyCache(); irr::EKEY_CODE keyname_to_keycode(const char *name); + +// Now with internal exception handling. return irr::KEY_KEY_CODES_COUNT on fail +irr::EKEY_CODE keyname_to_keycode_safemode(const char *name); diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index c59b93e88..132e31d2b 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -284,6 +284,7 @@ void set_default_settings() settings->setDefault("joystick_deadzone", "2048"); settings->setDefault("clickable_chat_weblinks", "false"); settings->setDefault("chat_weblink_color", "8888FF"); + settings->setDefault("chat_weblink_ctrl_keys", "KEY_LCONTROL,KEY_RCONTROL,KEY_CONTROL"); // Main menu settings->setDefault("main_menu_path", ""); diff --git a/src/gui/guiChatConsole.cpp b/src/gui/guiChatConsole.cpp index f5336e3ad..08d26efc2 100644 --- a/src/gui/guiChatConsole.cpp +++ b/src/gui/guiChatConsole.cpp @@ -90,8 +90,19 @@ GUIChatConsole::GUIChatConsole( // set default cursor options setCursor(true, true, 2.0, 0.1); - + m_cache_clickable_chat_weblinks = g_settings->getBool("clickable_chat_weblinks"); + if(m_cache_clickable_chat_weblinks) + { + std::string ctrlkeystoparse = g_settings->get("chat_weblink_ctrl_keys"); + if(setupChatClickCtrlKeys(ctrlkeystoparse) == 0) + { + // if fail then try again w hardcoded string + g_logger.log(LL_WARNING, "Failed to parse chat_weblink_ctrl_keys. Using hardcoded default."); + ctrlkeystoparse = "KEY_CONTROL,KEY_LCONTROL,KEY_RCONTROL"; + setupChatClickCtrlKeys(ctrlkeystoparse); + } + } } GUIChatConsole::~GUIChatConsole() @@ -412,7 +423,7 @@ bool GUIChatConsole::OnEvent(const SEvent& event) if(event.EventType == EET_KEY_INPUT_EVENT && !event.KeyInput.PressedDown) { // CTRL up - if(event.KeyInput.Key == KEY_LCONTROL || event.KeyInput.Key == KEY_RCONTROL || !event.KeyInput.Control) + if(isInCtrlKeys(event.KeyInput.Key) || !event.KeyInput.Control) { isctrldown = false; } @@ -420,7 +431,7 @@ bool GUIChatConsole::OnEvent(const SEvent& event) else if(event.EventType == EET_KEY_INPUT_EVENT && event.KeyInput.PressedDown) { // CTRL down - if(event.KeyInput.Key == KEY_LCONTROL || event.KeyInput.Key == KEY_RCONTROL || event.KeyInput.Control) + if(isInCtrlKeys(event.KeyInput.Key) || event.KeyInput.Control) { isctrldown = true; } @@ -669,3 +680,53 @@ void GUIChatConsole::setVisible(bool visible) } } +// Return how many "ctrl" keycodes successfully found in string, or 0 on fail +int GUIChatConsole::setupChatClickCtrlKeys(std::string inputline) +{ + m_cache_chat_weblink_ctrl_keys.clear(); + + irr::EKEY_CODE kc; + std::string stemp; + size_t startpos = 0, endpos = 0; + while(startpos < inputline.size()) + { + // Foreach delimited string, + endpos = inputline.find(',', startpos); + endpos = std::min(endpos, inputline.find(' ', startpos)); + // Ignore space/comma + if(endpos == startpos) + { + ++endpos; + } + // Ignore consecutive space/comma + else if(endpos - startpos > 1) + { + // If valid keycode, add it to cached list + stemp = inputline.substr(startpos, endpos - startpos); + kc = keyname_to_keycode_safemode(stemp.c_str()); + if(kc != irr::KEY_KEY_CODES_COUNT) + { + m_cache_chat_weblink_ctrl_keys.push_back(kc); + } + else + { + stemp = "Ignoring unknown keycode '" + stemp + "' for chat_weblink_ctrl_keys, check your conf"; + g_logger.log(LL_WARNING, stemp); + } + } + startpos = endpos; + } + + return m_cache_chat_weblink_ctrl_keys.size(); +} + +bool GUIChatConsole::isInCtrlKeys(const irr::EKEY_CODE& kc) +{ + // To avoid including + for(size_t i=0; i m_cache_chat_weblink_ctrl_keys; }; -- cgit v1.2.3 From fcb41bdc11eb9003f64f003b88940211f01002d7 Mon Sep 17 00:00:00 2001 From: pecksin Date: Fri, 19 Mar 2021 17:29:55 -0400 Subject: hopefully fix github check --- src/chat.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/chat.cpp b/src/chat.cpp index 7d8a3903f..a67371441 100644 --- a/src/chat.cpp +++ b/src/chat.cpp @@ -29,6 +29,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "util/string.h" #include "util/numeric.h" #include "porting.h" +#include "gettext.h" ChatBuffer::ChatBuffer(u32 scrollback): m_scrollback(scrollback) -- cgit v1.2.3 From 7054232044c1b0ccf50e80d40e5d3d8a37062415 Mon Sep 17 00:00:00 2001 From: pecksin Date: Mon, 22 Mar 2021 17:21:28 -0400 Subject: minor cleanup --- po/minetest.pot | 1 + src/chat.cpp | 14 ++------------ src/gui/guiChatConsole.cpp | 1 - src/gui/guiChatConsole.h | 2 +- 4 files changed, 4 insertions(+), 14 deletions(-) diff --git a/po/minetest.pot b/po/minetest.pot index 6f527022b..408995dc5 100644 --- a/po/minetest.pot +++ b/po/minetest.pot @@ -6364,3 +6364,4 @@ msgstr "" #: src/chat.cpp msgid "Failed to open webpage" msgstr "" + diff --git a/src/chat.cpp b/src/chat.cpp index a67371441..5a8afa908 100644 --- a/src/chat.cpp +++ b/src/chat.cpp @@ -37,6 +37,7 @@ ChatBuffer::ChatBuffer(u32 scrollback): if (m_scrollback == 0) m_scrollback = 1; m_empty_formatted_line.first = true; + m_cache_clickable_chat_weblinks = g_settings->getBool("clickable_chat_weblinks"); if(m_cache_clickable_chat_weblinks) { @@ -338,7 +339,7 @@ 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; - + if(!m_cache_clickable_chat_weblinks) { while (frag_length < remaining_in_input && @@ -440,17 +441,6 @@ u32 ChatBuffer::formatChatLine(const ChatLine& line, u32 cols, next_frags.push_back(temp_frag); in_pos += frag_length; remaining_in_output -= std::min(frag_length, remaining_in_output); - - /* - std::cout << "----------" << std::endl; - std::cout << "http_pos = " << http_pos << std::endl; - std::cout << "space_pos = " << space_pos << std::endl; - std::cout << "frag: '" << temp_frag.text.size() << "'" << std::endl; - std::cout << "in_pos: '" << in_pos << std::endl; - std::cout << "remain: '" << line.text.substr(in_pos).size() << "'" << std::endl; - std::cout << "remn in in: '" << remaining_in_input << "'" << std::endl; - std::cout << "remn in out: '" << remaining_in_output << "'" << std::endl; - */ } // handled for fragments individually text_processing = false; diff --git a/src/gui/guiChatConsole.cpp b/src/gui/guiChatConsole.cpp index 08d26efc2..527a28bdb 100644 --- a/src/gui/guiChatConsole.cpp +++ b/src/gui/guiChatConsole.cpp @@ -334,7 +334,6 @@ void GUIChatConsole::drawText() #if USE_FREETYPE if (m_font->getType() == irr::gui::EGFT_CUSTOM) { - // Draw colored text if FreeType is enabled irr::gui::CGUITTFont *tmp = dynamic_cast(m_font); tmp->draw( diff --git a/src/gui/guiChatConsole.h b/src/gui/guiChatConsole.h index 058b78f28..0618f2956 100644 --- a/src/gui/guiChatConsole.h +++ b/src/gui/guiChatConsole.h @@ -128,7 +128,7 @@ private: // font gui::IGUIFont *m_font = nullptr; v2u32 m_fontsize; - + // Enable clickable chat weblinks bool m_cache_clickable_chat_weblinks; // Set of "control" keys for weblink mouseclicks -- cgit v1.2.3 From f5e1b6eedcf0315fe1dd10e6deaf41f89b5cc589 Mon Sep 17 00:00:00 2001 From: pecksin Date: Mon, 22 Mar 2021 18:45:17 -0400 Subject: fixed segfault with libncurses --- src/chat.cpp | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/src/chat.cpp b/src/chat.cpp index 5a8afa908..b0223f8db 100644 --- a/src/chat.cpp +++ b/src/chat.cpp @@ -38,20 +38,24 @@ ChatBuffer::ChatBuffer(u32 scrollback): m_scrollback = 1; m_empty_formatted_line.first = true; - m_cache_clickable_chat_weblinks = g_settings->getBool("clickable_chat_weblinks"); - if(m_cache_clickable_chat_weblinks) + // Curses mode cannot access g_settings here + if(g_settings != NULL) { - 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,150,150,255); - m_cache_chat_weblink_color = irr::video::SColor(255,redval,greenval,blueval); + 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,150,150,255); + m_cache_chat_weblink_color = irr::video::SColor(255,redval,greenval,blueval); + } } } -- cgit v1.2.3 From 1b39c96683f984b82432cb9f9417245680982b41 Mon Sep 17 00:00:00 2001 From: pecksin Date: Mon, 22 Mar 2021 20:57:29 -0400 Subject: only use user-configured ctrl keys for weblink click --- src/gui/guiChatConsole.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gui/guiChatConsole.cpp b/src/gui/guiChatConsole.cpp index 527a28bdb..c27ade23d 100644 --- a/src/gui/guiChatConsole.cpp +++ b/src/gui/guiChatConsole.cpp @@ -422,7 +422,7 @@ bool GUIChatConsole::OnEvent(const SEvent& event) if(event.EventType == EET_KEY_INPUT_EVENT && !event.KeyInput.PressedDown) { // CTRL up - if(isInCtrlKeys(event.KeyInput.Key) || !event.KeyInput.Control) + if(isInCtrlKeys(event.KeyInput.Key)) { isctrldown = false; } @@ -430,7 +430,7 @@ bool GUIChatConsole::OnEvent(const SEvent& event) else if(event.EventType == EET_KEY_INPUT_EVENT && event.KeyInput.PressedDown) { // CTRL down - if(isInCtrlKeys(event.KeyInput.Key) || event.KeyInput.Control) + if(isInCtrlKeys(event.KeyInput.Key)) { isctrldown = true; } -- cgit v1.2.3 From c18be120855d4219d7e06ed674121eb7f6a93ea5 Mon Sep 17 00:00:00 2001 From: pecksin Date: Tue, 23 Mar 2021 01:17:18 -0400 Subject: minor cleanup --- src/chat.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/chat.cpp b/src/chat.cpp index b0223f8db..c58b6e7cb 100644 --- a/src/chat.cpp +++ b/src/chat.cpp @@ -53,7 +53,6 @@ ChatBuffer::ChatBuffer(u32 scrollback): colorval /= 256; redval = colorval % 256; // discard alpha, if included - //m_cache_chat_weblink_color = irr::video::SColor(255,150,150,255); m_cache_chat_weblink_color = irr::video::SColor(255,redval,greenval,blueval); } } @@ -423,7 +422,7 @@ u32 ChatBuffer::formatChatLine(const ChatLine& line, u32 cols, else { space_pos = http_pos - 1; - frag_length = http_pos; // - in_pos; + frag_length = http_pos; } if (space_pos != 0 && frag_length < remaining_in_input) @@ -434,7 +433,6 @@ u32 ChatBuffer::formatChatLine(const ChatLine& line, u32 cols, if(http_pos == 0) { temp_frag.meta = wide_to_utf8(temp_frag.text.getString()); - // FIXME: this is probably overkill to recolor the link text. temp_frag.text = EnrichedString(temp_frag.text.getString()); temp_frag.text.setDefaultColor(m_cache_chat_weblink_color); } -- cgit v1.2.3 From 7e8e3153e5227eb9b35ed2379efb54d17ba9aeae Mon Sep 17 00:00:00 2001 From: pecksin Date: Tue, 23 Mar 2021 18:18:44 -0400 Subject: move middleClick() into guiChatConsole.cpp where it belongs --- src/chat.cpp | 58 ---------------------------------------------- src/chat.h | 4 ---- src/gui/guiChatConsole.cpp | 58 +++++++++++++++++++++++++++++++++++++++++++++- src/gui/guiChatConsole.h | 4 +++- 4 files changed, 60 insertions(+), 64 deletions(-) diff --git a/src/chat.cpp b/src/chat.cpp index c58b6e7cb..9bceb3535 100644 --- a/src/chat.cpp +++ b/src/chat.cpp @@ -28,8 +28,6 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "util/strfnd.h" #include "util/string.h" #include "util/numeric.h" -#include "porting.h" -#include "gettext.h" ChatBuffer::ChatBuffer(u32 scrollback): m_scrollback(scrollback) @@ -886,59 +884,3 @@ void ChatBackend::scrollPageUp() { m_console_buffer.scroll(-(s32)m_console_buffer.getRows()); } - -void ChatBackend::middleClick(s32 col, s32 row) -{ - // Prevent accidental rapid clicking - static u32 oldtime = 0; - // seriously.. - u32 newtime = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); - - // 0.6 seconds should suffice - if(newtime - oldtime < 600) - return; - oldtime = newtime; - - const std::vector & frags = getConsoleBuffer().getFormattedLine(row).fragments; - std::string weblink = ""; // from frag meta - - // Identify targetted fragment, if exists - int ind = frags.size() - 1; - while(u32(col - 1) < frags[ind].column) - { - --ind; - } - if(ind > -1) - { - weblink = frags[ind].meta; - } - - // Debug help - std::string ws; - ws = "Middleclick: (" + std::to_string(col) + ',' + std::to_string(row) + ')' + " frags:"; - for(u32 i=0;imiddleClick(event.MouseInput.X / m_fontsize.X, event.MouseInput.Y / m_fontsize.Y); + middleClick(event.MouseInput.X / m_fontsize.X, event.MouseInput.Y / m_fontsize.Y); } } } @@ -729,3 +729,59 @@ bool GUIChatConsole::isInCtrlKeys(const irr::EKEY_CODE& kc) } return false; } + +void GUIChatConsole::middleClick(s32 col, s32 row) +{ + // Prevent accidental rapid clicking + static u32 oldtime = 0; + // seriously.. + u32 newtime = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); + + // 0.6 seconds should suffice + if(newtime - oldtime < 600) + return; + oldtime = newtime; + + const std::vector & frags = m_chat_backend->getConsoleBuffer().getFormattedLine(row).fragments; + std::string weblink = ""; // from frag meta + + // Identify targetted fragment, if exists + int ind = frags.size() - 1; + while(u32(col - 1) < frags[ind].column) + { + --ind; + } + if(ind > -1) + { + weblink = frags[ind].meta; + } + + // Debug help + std::string ws; + ws = "Middleclick: (" + std::to_string(col) + ',' + std::to_string(row) + ')' + " frags:"; + for(u32 i=0;iaddUnparsedMessage(utf8_to_wide(mesg)); + } +} diff --git a/src/gui/guiChatConsole.h b/src/gui/guiChatConsole.h index 0618f2956..169fb7eb7 100644 --- a/src/gui/guiChatConsole.h +++ b/src/gui/guiChatConsole.h @@ -82,9 +82,11 @@ private: void drawText(); void drawPrompt(); - // Parse conf and populate "ctrl" keys for clickable chat + // Clickable weblink stuff int setupChatClickCtrlKeys(std::string inputline); bool isInCtrlKeys(const irr::EKEY_CODE& kc); + // If clicked fragment has a web url, send it to the system default web browser + void middleClick(s32 col, s32 row); private: ChatBackend* m_chat_backend; -- cgit v1.2.3