]> git.lizzy.rs Git - dragonfireclient.git/blobdiff - src/guiChatConsole.cpp
Decoration API: Allow force_placement of simple decorations
[dragonfireclient.git] / src / guiChatConsole.cpp
index 5fc576cf8315f83c8a5b6268a83b79c507c43660..d59937c31df3f9367218e88c2600c3ddfb30a833 100644 (file)
@@ -24,13 +24,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "gettime.h"
 #include "keycode.h"
 #include "settings.h"
-#include "main.h"  // for g_settings
 #include "porting.h"
-#include "tile.h"
-#include "IGUIFont.h"
-#include <string>
-
+#include "client/tile.h"
+#include "fontengine.h"
+#include "log.h"
 #include "gettext.h"
+#include <string>
 
 #if USE_FREETYPE
 #include "xCGUITTFont.h"
@@ -47,15 +46,18 @@ GUIChatConsole::GUIChatConsole(
                gui::IGUIElement* parent,
                s32 id,
                ChatBackend* backend,
-               Client* client
+               Client* client,
+               IMenuManager* menumgr
 ):
        IGUIElement(gui::EGUIET_ELEMENT, env, parent, id,
                        core::rect<s32>(0,0,100,100)),
        m_chat_backend(backend),
        m_client(client),
+       m_menumgr(menumgr),
        m_screensize(v2u32(0,0)),
        m_animate_time_old(0),
        m_open(false),
+       m_close_on_enter(false),
        m_height(0),
        m_desired_height(0),
        m_desired_height_fraction(0.0),
@@ -72,45 +74,34 @@ GUIChatConsole::GUIChatConsole(
        m_animate_time_old = getTimeMs();
 
        // load background settings
-       bool console_color_set = !g_settings->get("console_color").empty();
        s32 console_alpha = g_settings->getS32("console_alpha");
+       m_background_color.setAlpha(clamp_u8(console_alpha));
 
        // load the background texture depending on settings
-       m_background_color.setAlpha(clamp_u8(console_alpha));
-       if (console_color_set)
-       {
+       ITextureSource *tsrc = client->getTextureSource();
+       if (tsrc->isKnownSourceImage("background_chat.jpg")) {
+               m_background = tsrc->getTexture("background_chat.jpg");
+               m_background_color.setRed(255);
+               m_background_color.setGreen(255);
+               m_background_color.setBlue(255);
+       } else {
                v3f console_color = g_settings->getV3F("console_color");
                m_background_color.setRed(clamp_u8(myround(console_color.X)));
                m_background_color.setGreen(clamp_u8(myround(console_color.Y)));
                m_background_color.setBlue(clamp_u8(myround(console_color.Z)));
        }
-       else
-       {
-               m_background = env->getVideoDriver()->getTexture(getTexturePath("background_chat.jpg").c_str());
-               m_background_color.setRed(255);
-               m_background_color.setGreen(255);
-               m_background_color.setBlue(255);
-       }
 
-       // load the font
-       // FIXME should a custom texture_path be searched too?
-       #if USE_FREETYPE
-       std::string font_name = g_settings->get("mono_font_path");
-       u16 font_size = g_settings->getU16("mono_font_size");
-       m_font = gui::CGUITTFont::createTTFont(env, font_name.c_str(), font_size);
-       #else
-       std::string font_name = "fontdejavusansmono.png";
-       m_font = env->getFont(getTexturePath(font_name).c_str());
-       #endif
+       m_font = g_fontengine->getFont(FONT_SIZE_UNSPECIFIED, FM_Mono);
+
        if (m_font == NULL)
        {
-               dstream << "Unable to load font: " << font_name << std::endl;
+               errorstream << "GUIChatConsole: Unable to load mono font ";
        }
        else
        {
                core::dimension2d<u32> dim = m_font->getDimension(L"M");
                m_fontsize = v2u32(dim.Width, dim.Height);
-               dstream << "Font size: " << m_fontsize.X << " " << m_fontsize.Y << std::endl;
+               m_font->grab();
        }
        m_fontsize.X = MYMAX(m_fontsize.X, 1);
        m_fontsize.Y = MYMAX(m_fontsize.Y, 1);
@@ -121,6 +112,8 @@ GUIChatConsole::GUIChatConsole(
 
 GUIChatConsole::~GUIChatConsole()
 {
+       if (m_font)
+               m_font->drop();
 }
 
 void GUIChatConsole::openConsole(f32 height)
@@ -129,6 +122,13 @@ void GUIChatConsole::openConsole(f32 height)
        m_desired_height_fraction = height;
        m_desired_height = height * m_screensize.Y;
        reformatConsole();
+       Environment->setFocus(this);
+       m_menumgr->createdMenu(this);
+}
+
+bool GUIChatConsole::isOpen() const
+{
+       return m_open;
 }
 
 bool GUIChatConsole::isOpenInhibited() const
@@ -139,11 +139,13 @@ bool GUIChatConsole::isOpenInhibited() const
 void GUIChatConsole::closeConsole()
 {
        m_open = false;
+       Environment->removeFocus(this);
+       m_menumgr->deletingMenu(this);
 }
 
 void GUIChatConsole::closeConsoleAtOnce()
 {
-       m_open = false;
+       closeConsole();
        m_height = 0;
        recalculateConsolePosition();
 }
@@ -153,6 +155,14 @@ f32 GUIChatConsole::getDesiredHeight() const
        return m_desired_height_fraction;
 }
 
+void GUIChatConsole::replaceAndAddToHistory(std::wstring line)
+{
+       ChatPrompt& prompt = m_chat_backend->getPrompt();
+       prompt.addToHistory(prompt.getLine());
+       prompt.replace(line);
+}
+
+
 void GUIChatConsole::setCursor(
        bool visible, bool blinking, f32 blink_speed, f32 relative_height)
 {
@@ -367,13 +377,15 @@ void GUIChatConsole::drawPrompt()
                s32 cursor_pos = prompt.getVisibleCursorPosition();
                if (cursor_pos >= 0)
                {
+                       s32 cursor_len = prompt.getCursorLength();
                        video::IVideoDriver* driver = Environment->getVideoDriver();
                        s32 x = (1 + cursor_pos) * m_fontsize.X;
                        core::rect<s32> destrect(
                                x,
-                               y + (1.0-m_cursor_height) * m_fontsize.Y,
-                               x + m_fontsize.X,
-                               y + m_fontsize.Y);
+                               y + m_fontsize.Y * (1.0 - m_cursor_height),
+                               x + m_fontsize.X * MYMAX(cursor_len, 1),
+                               y + m_fontsize.Y * (cursor_len ? m_cursor_height+1 : 1)
+                       );
                        video::SColor cursor_color(255,255,255,255);
                        driver->draw2DRectangle(
                                cursor_color,
@@ -386,23 +398,27 @@ void GUIChatConsole::drawPrompt()
 
 bool GUIChatConsole::OnEvent(const SEvent& event)
 {
+
+       ChatPrompt &prompt = m_chat_backend->getPrompt();
+
        if(event.EventType == EET_KEY_INPUT_EVENT && event.KeyInput.PressedDown)
        {
                // Key input
                if(KeyPress(event.KeyInput) == getKeySetting("keymap_console"))
                {
                        closeConsole();
-                       Environment->removeFocus(this);
 
                        // inhibit open so the_game doesn't reopen immediately
                        m_open_inhibited = 50;
+                       m_close_on_enter = false;
                        return true;
                }
                else if(event.KeyInput.Key == KEY_ESCAPE)
                {
                        closeConsoleAtOnce();
-                       Environment->removeFocus(this);
-                       // the_game will open the pause menu
+                       m_close_on_enter = false;
+                       // inhibit open so the_game doesn't reopen immediately
+                       m_open_inhibited = 1; // so the ESCAPE button doesn't open the "pause menu"
                        return true;
                }
                else if(event.KeyInput.Key == KEY_PRIOR)
@@ -417,57 +433,50 @@ bool GUIChatConsole::OnEvent(const SEvent& event)
                }
                else if(event.KeyInput.Key == KEY_RETURN)
                {
-                       std::wstring text = m_chat_backend->getPrompt().submit();
+                       prompt.addToHistory(prompt.getLine());
+                       std::wstring text = prompt.replace(L"");
                        m_client->typeChatMessage(text);
+                       if (m_close_on_enter) {
+                               closeConsoleAtOnce();
+                               m_close_on_enter = false;
+                       }
                        return true;
                }
                else if(event.KeyInput.Key == KEY_UP)
                {
                        // Up pressed
                        // Move back in history
-                       m_chat_backend->getPrompt().historyPrev();
+                       prompt.historyPrev();
                        return true;
                }
                else if(event.KeyInput.Key == KEY_DOWN)
                {
                        // Down pressed
                        // Move forward in history
-                       m_chat_backend->getPrompt().historyNext();
+                       prompt.historyNext();
                        return true;
                }
-               else if(event.KeyInput.Key == KEY_LEFT)
+               else if(event.KeyInput.Key == KEY_LEFT || event.KeyInput.Key == KEY_RIGHT)
                {
-                       // Left or Ctrl-Left pressed
-                       // move character / word to the left
-                       ChatPrompt::CursorOpScope scope =
-                               event.KeyInput.Control ?
-                               ChatPrompt::CURSOROP_SCOPE_WORD :
-                               ChatPrompt::CURSOROP_SCOPE_CHARACTER;
-                       m_chat_backend->getPrompt().cursorOperation(
-                               ChatPrompt::CURSOROP_MOVE,
-                               ChatPrompt::CURSOROP_DIR_LEFT,
-                               scope);
-                       return true;
-               }
-               else if(event.KeyInput.Key == KEY_RIGHT)
-               {
-                       // Right or Ctrl-Right pressed
-                       // move character / word to the right
-                       ChatPrompt::CursorOpScope scope =
-                               event.KeyInput.Control ?
+                       // Left/right pressed
+                       // Move/select character/word to the left depending on control and shift keys
+                       ChatPrompt::CursorOp op = event.KeyInput.Shift ?
+                               ChatPrompt::CURSOROP_SELECT :
+                               ChatPrompt::CURSOROP_MOVE;
+                       ChatPrompt::CursorOpDir dir = event.KeyInput.Key == KEY_LEFT ?
+                               ChatPrompt::CURSOROP_DIR_LEFT :
+                               ChatPrompt::CURSOROP_DIR_RIGHT;
+                       ChatPrompt::CursorOpScope scope = event.KeyInput.Control ?
                                ChatPrompt::CURSOROP_SCOPE_WORD :
                                ChatPrompt::CURSOROP_SCOPE_CHARACTER;
-                       m_chat_backend->getPrompt().cursorOperation(
-                               ChatPrompt::CURSOROP_MOVE,
-                               ChatPrompt::CURSOROP_DIR_RIGHT,
-                               scope);
+                       prompt.cursorOperation(op, dir, scope);
                        return true;
                }
                else if(event.KeyInput.Key == KEY_HOME)
                {
                        // Home pressed
                        // move to beginning of line
-                       m_chat_backend->getPrompt().cursorOperation(
+                       prompt.cursorOperation(
                                ChatPrompt::CURSOROP_MOVE,
                                ChatPrompt::CURSOROP_DIR_LEFT,
                                ChatPrompt::CURSOROP_SCOPE_LINE);
@@ -477,7 +486,7 @@ bool GUIChatConsole::OnEvent(const SEvent& event)
                {
                        // End pressed
                        // move to end of line
-                       m_chat_backend->getPrompt().cursorOperation(
+                       prompt.cursorOperation(
                                ChatPrompt::CURSOROP_MOVE,
                                ChatPrompt::CURSOROP_DIR_RIGHT,
                                ChatPrompt::CURSOROP_SCOPE_LINE);
@@ -491,7 +500,7 @@ bool GUIChatConsole::OnEvent(const SEvent& event)
                                event.KeyInput.Control ?
                                ChatPrompt::CURSOROP_SCOPE_WORD :
                                ChatPrompt::CURSOROP_SCOPE_CHARACTER;
-                       m_chat_backend->getPrompt().cursorOperation(
+                       prompt.cursorOperation(
                                ChatPrompt::CURSOROP_DELETE,
                                ChatPrompt::CURSOROP_DIR_LEFT,
                                scope);
@@ -505,17 +514,72 @@ bool GUIChatConsole::OnEvent(const SEvent& event)
                                event.KeyInput.Control ?
                                ChatPrompt::CURSOROP_SCOPE_WORD :
                                ChatPrompt::CURSOROP_SCOPE_CHARACTER;
-                       m_chat_backend->getPrompt().cursorOperation(
+                       prompt.cursorOperation(
                                ChatPrompt::CURSOROP_DELETE,
                                ChatPrompt::CURSOROP_DIR_RIGHT,
                                scope);
                        return true;
                }
+               else if(event.KeyInput.Key == KEY_KEY_A && event.KeyInput.Control)
+               {
+                       // Ctrl-A pressed
+                       // Select all text
+                       prompt.cursorOperation(
+                               ChatPrompt::CURSOROP_SELECT,
+                               ChatPrompt::CURSOROP_DIR_LEFT, // Ignored
+                               ChatPrompt::CURSOROP_SCOPE_LINE);
+                       return true;
+               }
+               else if(event.KeyInput.Key == KEY_KEY_C && event.KeyInput.Control)
+               {
+                       // Ctrl-C pressed
+                       // Copy text to clipboard
+                       if (prompt.getCursorLength() <= 0)
+                               return true;
+                       std::wstring wselected = prompt.getSelection();
+                       std::string selected(wselected.begin(), wselected.end());
+                       Environment->getOSOperator()->copyToClipboard(selected.c_str());
+                       return true;
+               }
+               else if(event.KeyInput.Key == KEY_KEY_V && event.KeyInput.Control)
+               {
+                       // Ctrl-V pressed
+                       // paste text from clipboard
+                       if (prompt.getCursorLength() > 0) {
+                               // Delete selected section of text
+                               prompt.cursorOperation(
+                                       ChatPrompt::CURSOROP_DELETE,
+                                       ChatPrompt::CURSOROP_DIR_LEFT, // Ignored
+                                       ChatPrompt::CURSOROP_SCOPE_SELECTION);
+                       }
+                       IOSOperator *os_operator = Environment->getOSOperator();
+                       const c8 *text = os_operator->getTextFromClipboard();
+                       if (!text)
+                               return true;
+                       std::basic_string<unsigned char> str((const unsigned char*)text);
+                       prompt.input(std::wstring(str.begin(), str.end()));
+                       return true;
+               }
+               else if(event.KeyInput.Key == KEY_KEY_X && event.KeyInput.Control)
+               {
+                       // Ctrl-X pressed
+                       // Cut text to clipboard
+                       if (prompt.getCursorLength() <= 0)
+                               return true;
+                       std::wstring wselected = prompt.getSelection();
+                       std::string selected(wselected.begin(), wselected.end());
+                       Environment->getOSOperator()->copyToClipboard(selected.c_str());
+                       prompt.cursorOperation(
+                               ChatPrompt::CURSOROP_DELETE,
+                               ChatPrompt::CURSOROP_DIR_LEFT, // Ignored
+                               ChatPrompt::CURSOROP_SCOPE_SELECTION);
+                       return true;
+               }
                else if(event.KeyInput.Key == KEY_KEY_U && event.KeyInput.Control)
                {
                        // Ctrl-U pressed
                        // kill line to left end
-                       m_chat_backend->getPrompt().cursorOperation(
+                       prompt.cursorOperation(
                                ChatPrompt::CURSOROP_DELETE,
                                ChatPrompt::CURSOROP_DIR_LEFT,
                                ChatPrompt::CURSOROP_SCOPE_LINE);
@@ -525,7 +589,7 @@ bool GUIChatConsole::OnEvent(const SEvent& event)
                {
                        // Ctrl-K pressed
                        // kill line to right end
-                       m_chat_backend->getPrompt().cursorOperation(
+                       prompt.cursorOperation(
                                ChatPrompt::CURSOROP_DELETE,
                                ChatPrompt::CURSOROP_DIR_RIGHT,
                                ChatPrompt::CURSOROP_SCOPE_LINE);
@@ -535,14 +599,20 @@ bool GUIChatConsole::OnEvent(const SEvent& event)
                {
                        // Tab or Shift-Tab pressed
                        // Nick completion
-                       std::list<std::wstring> names = m_client->getConnectedPlayerNames();
+                       std::list<std::string> names = m_client->getConnectedPlayerNames();
                        bool backwards = event.KeyInput.Shift;
-                       m_chat_backend->getPrompt().nickCompletion(names, backwards);
+                       prompt.nickCompletion(names, backwards);
                        return true;
                }
                else if(event.KeyInput.Char != 0 && !event.KeyInput.Control)
                {
-                       m_chat_backend->getPrompt().input(event.KeyInput.Char);
+                       #if (defined(linux) || defined(__linux))
+                               wchar_t wc = L'_';
+                               mbtowc( &wc, (char *) &event.KeyInput.Char, sizeof(event.KeyInput.Char) );
+                               prompt.input(wc);
+                       #else
+                               prompt.input(event.KeyInput.Char);
+                       #endif
                        return true;
                }
        }