]> git.lizzy.rs Git - dragonfireclient.git/blobdiff - src/gui/guiEditBox.cpp
add airjump and remove unused headers
[dragonfireclient.git] / src / gui / guiEditBox.cpp
index 159bd38ac9bc6bc4d660ce1601397e84d0745ebd..ba548aa2d69a0c8badcf8f435d1b1794baeb6fb6 100644 (file)
@@ -19,14 +19,23 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 
 #include "guiEditBox.h"
 
+#include "IrrCompileConfig.h"
 #include "IGUISkin.h"
 #include "IGUIEnvironment.h"
 #include "IGUIFont.h"
 
+#include "porting.h"
+
 GUIEditBox::~GUIEditBox()
 {
        if (m_override_font)
                m_override_font->drop();
+
+       if (m_operator)
+               m_operator->drop();
+
+       if (m_vscrollbar)
+               m_vscrollbar->drop();
 }
 
 void GUIEditBox::setOverrideFont(IGUIFont *font)
@@ -93,3 +102,800 @@ void GUIEditBox::setAutoScroll(bool enable)
 {
        m_autoscroll = enable;
 }
+
+void GUIEditBox::setPasswordBox(bool password_box, wchar_t password_char)
+{
+       m_passwordbox = password_box;
+       if (m_passwordbox) {
+               m_passwordchar = password_char;
+               setMultiLine(false);
+               setWordWrap(false);
+               m_broken_text.clear();
+       }
+}
+
+//! Sets text justification
+void GUIEditBox::setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT vertical)
+{
+       m_halign = horizontal;
+       m_valign = vertical;
+}
+
+//! Sets the new caption of this element.
+void GUIEditBox::setText(const wchar_t *text)
+{
+       Text = text;
+       if (u32(m_cursor_pos) > Text.size())
+               m_cursor_pos = Text.size();
+       m_hscroll_pos = 0;
+       breakText();
+}
+
+//! Sets the maximum amount of characters which may be entered in the box.
+//! \param max: Maximum amount of characters. If 0, the character amount is
+//! infinity.
+void GUIEditBox::setMax(u32 max)
+{
+       m_max = max;
+
+       if (Text.size() > m_max && m_max != 0)
+               Text = Text.subString(0, m_max);
+}
+
+//! Gets the area of the text in the edit box
+//! \return Returns the size in pixels of the text
+core::dimension2du GUIEditBox::getTextDimension()
+{
+       core::rect<s32> ret;
+
+       setTextRect(0);
+       ret = m_current_text_rect;
+
+       for (u32 i = 1; i < m_broken_text.size(); ++i) {
+               setTextRect(i);
+               ret.addInternalPoint(m_current_text_rect.UpperLeftCorner);
+               ret.addInternalPoint(m_current_text_rect.LowerRightCorner);
+       }
+
+       return core::dimension2du(ret.getSize());
+}
+
+//! Turns the border on or off
+void GUIEditBox::setDrawBorder(bool border)
+{
+       m_border = border;
+}
+
+void GUIEditBox::setWritable(bool can_write_text)
+{
+       m_writable = can_write_text;
+}
+
+//! set text markers
+void GUIEditBox::setTextMarkers(s32 begin, s32 end)
+{
+       if (begin != m_mark_begin || end != m_mark_end) {
+               m_mark_begin = begin;
+               m_mark_end = end;
+               sendGuiEvent(EGET_EDITBOX_MARKING_CHANGED);
+       }
+}
+
+//! send some gui event to parent
+void GUIEditBox::sendGuiEvent(EGUI_EVENT_TYPE type)
+{
+       if (Parent) {
+               SEvent e;
+               e.EventType = EET_GUI_EVENT;
+               e.GUIEvent.Caller = this;
+               e.GUIEvent.Element = 0;
+               e.GUIEvent.EventType = type;
+
+               Parent->OnEvent(e);
+       }
+}
+
+//! called if an event happened.
+bool GUIEditBox::OnEvent(const SEvent &event)
+{
+       if (isEnabled()) {
+
+               switch (event.EventType) {
+               case EET_GUI_EVENT:
+                       if (event.GUIEvent.EventType == EGET_ELEMENT_FOCUS_LOST) {
+                               if (event.GUIEvent.Caller == this) {
+                                       m_mouse_marking = false;
+                                       setTextMarkers(0, 0);
+                               }
+                       }
+                       break;
+               case EET_KEY_INPUT_EVENT:
+                       if (processKey(event))
+                               return true;
+                       break;
+               case EET_MOUSE_INPUT_EVENT:
+                       if (processMouse(event))
+                               return true;
+                       break;
+#if (IRRLICHT_VERSION_MT_REVISION >= 2)
+               case EET_STRING_INPUT_EVENT:
+                       inputString(*event.StringInput.Str);
+                       return true;
+#endif
+               default:
+                       break;
+               }
+       }
+
+       return IGUIElement::OnEvent(event);
+}
+
+bool GUIEditBox::processKey(const SEvent &event)
+{
+       if (!m_writable) {
+               return false;
+       }
+
+       if (!event.KeyInput.PressedDown)
+               return false;
+
+       bool text_changed = false;
+       s32 new_mark_begin = m_mark_begin;
+       s32 new_mark_end = m_mark_end;
+
+       // control shortcut handling
+       if (event.KeyInput.Control) {
+
+               // german backlash '\' entered with control + '?'
+               if (event.KeyInput.Char == '\\') {
+                       inputChar(event.KeyInput.Char);
+                       return true;
+               }
+
+               switch (event.KeyInput.Key) {
+               case KEY_KEY_A:
+                       // select all
+                       new_mark_begin = 0;
+                       new_mark_end = Text.size();
+                       break;
+               case KEY_KEY_C:
+                       onKeyControlC(event);
+                       break;
+               case KEY_KEY_X:
+                       text_changed = onKeyControlX(event, new_mark_begin, new_mark_end);
+                       break;
+               case KEY_KEY_V:
+                       text_changed = onKeyControlV(event, new_mark_begin, new_mark_end);
+                       break;
+               case KEY_HOME:
+                       // move/highlight to start of text
+                       if (event.KeyInput.Shift) {
+                               new_mark_end = m_cursor_pos;
+                               new_mark_begin = 0;
+                               m_cursor_pos = 0;
+                       } else {
+                               m_cursor_pos = 0;
+                               new_mark_begin = 0;
+                               new_mark_end = 0;
+                       }
+                       break;
+               case KEY_END:
+                       // move/highlight to end of text
+                       if (event.KeyInput.Shift) {
+                               new_mark_begin = m_cursor_pos;
+                               new_mark_end = Text.size();
+                               m_cursor_pos = 0;
+                       } else {
+                               m_cursor_pos = Text.size();
+                               new_mark_begin = 0;
+                               new_mark_end = 0;
+                       }
+                       break;
+               default:
+                       return false;
+               }
+       } else {
+               switch (event.KeyInput.Key) {
+               case KEY_END: {
+                       s32 p = Text.size();
+                       if (m_word_wrap || m_multiline) {
+                               p = getLineFromPos(m_cursor_pos);
+                               p = m_broken_text_positions[p] +
+                                   (s32)m_broken_text[p].size();
+                               if (p > 0 && (Text[p - 1] == L'\r' ||
+                                                            Text[p - 1] == L'\n'))
+                                       p -= 1;
+                       }
+
+                       if (event.KeyInput.Shift) {
+                               if (m_mark_begin == m_mark_end)
+                                       new_mark_begin = m_cursor_pos;
+
+                               new_mark_end = p;
+                       } else {
+                               new_mark_begin = 0;
+                               new_mark_end = 0;
+                       }
+                       m_cursor_pos = p;
+                       m_blink_start_time = porting::getTimeMs();
+               } break;
+               case KEY_HOME: {
+
+                       s32 p = 0;
+                       if (m_word_wrap || m_multiline) {
+                               p = getLineFromPos(m_cursor_pos);
+                               p = m_broken_text_positions[p];
+                       }
+
+                       if (event.KeyInput.Shift) {
+                               if (m_mark_begin == m_mark_end)
+                                       new_mark_begin = m_cursor_pos;
+                               new_mark_end = p;
+                       } else {
+                               new_mark_begin = 0;
+                               new_mark_end = 0;
+                       }
+                       m_cursor_pos = p;
+                       m_blink_start_time = porting::getTimeMs();
+               } break;
+               case KEY_RETURN:
+                       if (m_multiline) {
+                               inputChar(L'\n');
+                       } else {
+                               calculateScrollPos();
+                               sendGuiEvent(EGET_EDITBOX_ENTER);
+                       }
+                       return true;
+               case KEY_LEFT:
+                       if (event.KeyInput.Shift) {
+                               if (m_cursor_pos > 0) {
+                                       if (m_mark_begin == m_mark_end)
+                                               new_mark_begin = m_cursor_pos;
+
+                                       new_mark_end = m_cursor_pos - 1;
+                               }
+                       } else {
+                               new_mark_begin = 0;
+                               new_mark_end = 0;
+                       }
+
+                       if (m_cursor_pos > 0)
+                               m_cursor_pos--;
+                       m_blink_start_time = porting::getTimeMs();
+                       break;
+               case KEY_RIGHT:
+                       if (event.KeyInput.Shift) {
+                               if (Text.size() > (u32)m_cursor_pos) {
+                                       if (m_mark_begin == m_mark_end)
+                                               new_mark_begin = m_cursor_pos;
+
+                                       new_mark_end = m_cursor_pos + 1;
+                               }
+                       } else {
+                               new_mark_begin = 0;
+                               new_mark_end = 0;
+                       }
+
+                       if (Text.size() > (u32)m_cursor_pos)
+                               m_cursor_pos++;
+                       m_blink_start_time = porting::getTimeMs();
+                       break;
+               case KEY_UP:
+                       if (!onKeyUp(event, new_mark_begin, new_mark_end)) {
+                               return false;
+                       }
+                       break;
+               case KEY_DOWN:
+                       if (!onKeyDown(event, new_mark_begin, new_mark_end)) {
+                               return false;
+                       }
+                       break;
+               case KEY_BACK:
+                       text_changed = onKeyBack(event, new_mark_begin, new_mark_end);
+                       break;
+
+               case KEY_DELETE:
+                       text_changed = onKeyDelete(event, new_mark_begin, new_mark_end);
+                       break;
+
+               case KEY_ESCAPE:
+               case KEY_TAB:
+               case KEY_SHIFT:
+               case KEY_F1:
+               case KEY_F2:
+               case KEY_F3:
+               case KEY_F4:
+               case KEY_F5:
+               case KEY_F6:
+               case KEY_F7:
+               case KEY_F8:
+               case KEY_F9:
+               case KEY_F10:
+               case KEY_F11:
+               case KEY_F12:
+               case KEY_F13:
+               case KEY_F14:
+               case KEY_F15:
+               case KEY_F16:
+               case KEY_F17:
+               case KEY_F18:
+               case KEY_F19:
+               case KEY_F20:
+               case KEY_F21:
+               case KEY_F22:
+               case KEY_F23:
+               case KEY_F24:
+                       // ignore these keys
+                       return false;
+
+               default:
+                       inputChar(event.KeyInput.Char);
+                       return true;
+               }
+       }
+
+       // Set new text markers
+       setTextMarkers(new_mark_begin, new_mark_end);
+
+       // break the text if it has changed
+       if (text_changed) {
+               breakText();
+               sendGuiEvent(EGET_EDITBOX_CHANGED);
+       }
+
+       calculateScrollPos();
+
+       return true;
+}
+
+bool GUIEditBox::onKeyUp(const SEvent &event, s32 &mark_begin, s32 &mark_end)
+{
+       // clang-format off
+       if (m_multiline || (m_word_wrap && m_broken_text.size() > 1)) {
+               s32 lineNo = getLineFromPos(m_cursor_pos);
+               s32 mb = (m_mark_begin == m_mark_end) ? m_cursor_pos :
+                       (m_mark_begin > m_mark_end ? m_mark_begin : m_mark_end);
+               if (lineNo > 0) {
+                       s32 cp = m_cursor_pos - m_broken_text_positions[lineNo];
+                       if ((s32)m_broken_text[lineNo - 1].size() < cp) {
+                               m_cursor_pos = m_broken_text_positions[lineNo - 1] +
+                                       core::max_((u32)1, m_broken_text[lineNo - 1].size()) - 1;
+                       }
+                       else
+                               m_cursor_pos = m_broken_text_positions[lineNo - 1] + cp;
+               }
+
+               if (event.KeyInput.Shift) {
+                       mark_begin = mb;
+                       mark_end = m_cursor_pos;
+               } else {
+                       mark_begin = 0;
+                       mark_end = 0;
+               }
+
+               return true;
+       }
+
+       // clang-format on
+       return false;
+}
+
+bool GUIEditBox::onKeyDown(const SEvent &event, s32 &mark_begin, s32 &mark_end)
+{
+       // clang-format off
+       if (m_multiline || (m_word_wrap && m_broken_text.size() > 1)) {
+               s32 lineNo = getLineFromPos(m_cursor_pos);
+               s32 mb = (m_mark_begin == m_mark_end) ? m_cursor_pos :
+                       (m_mark_begin < m_mark_end ? m_mark_begin : m_mark_end);
+               if (lineNo < (s32)m_broken_text.size() - 1) {
+                       s32 cp = m_cursor_pos - m_broken_text_positions[lineNo];
+                       if ((s32)m_broken_text[lineNo + 1].size() < cp) {
+                               m_cursor_pos = m_broken_text_positions[lineNo + 1] +
+                                       core::max_((u32)1, m_broken_text[lineNo + 1].size()) - 1;
+                       }
+                       else
+                               m_cursor_pos = m_broken_text_positions[lineNo + 1] + cp;
+               }
+
+               if (event.KeyInput.Shift) {
+                       mark_begin = mb;
+                       mark_end = m_cursor_pos;
+               } else {
+                       mark_begin = 0;
+                       mark_end = 0;
+               }
+
+               return true;
+       }
+
+       // clang-format on
+       return false;
+}
+
+void GUIEditBox::onKeyControlC(const SEvent &event)
+{
+       // copy to clipboard
+       if (m_passwordbox || !m_operator || m_mark_begin == m_mark_end)
+               return;
+
+       const s32 realmbgn = m_mark_begin < m_mark_end ? m_mark_begin : m_mark_end;
+       const s32 realmend = m_mark_begin < m_mark_end ? m_mark_end : m_mark_begin;
+
+       core::stringc s;
+       s = Text.subString(realmbgn, realmend - realmbgn).c_str();
+       m_operator->copyToClipboard(s.c_str());
+}
+
+bool GUIEditBox::onKeyControlX(const SEvent &event, s32 &mark_begin, s32 &mark_end)
+{
+       // First copy to clipboard
+       onKeyControlC(event);
+
+       if (m_passwordbox || !m_operator || m_mark_begin == m_mark_end)
+               return false;
+
+       const s32 realmbgn = m_mark_begin < m_mark_end ? m_mark_begin : m_mark_end;
+       const s32 realmend = m_mark_begin < m_mark_end ? m_mark_end : m_mark_begin;
+
+       // Now remove from box if enabled
+       if (isEnabled()) {
+               // delete
+               core::stringw s;
+               s = Text.subString(0, realmbgn);
+               s.append(Text.subString(realmend, Text.size() - realmend));
+               Text = s;
+
+               m_cursor_pos = realmbgn;
+               mark_begin = 0;
+               mark_end = 0;
+               return true;
+       }
+
+       return false;
+}
+
+bool GUIEditBox::onKeyControlV(const SEvent &event, s32 &mark_begin, s32 &mark_end)
+{
+       if (!isEnabled())
+               return false;
+
+       // paste from the clipboard
+       if (!m_operator)
+               return false;
+
+       const s32 realmbgn = m_mark_begin < m_mark_end ? m_mark_begin : m_mark_end;
+       const s32 realmend = m_mark_begin < m_mark_end ? m_mark_end : m_mark_begin;
+
+       // add new character
+       if (const c8 *p = m_operator->getTextFromClipboard()) {
+               if (m_mark_begin == m_mark_end) {
+                       // insert text
+                       core::stringw s = Text.subString(0, m_cursor_pos);
+                       s.append(p);
+                       s.append(Text.subString(
+                                       m_cursor_pos, Text.size() - m_cursor_pos));
+
+                       if (!m_max || s.size() <= m_max) {
+                               Text = s;
+                               s = p;
+                               m_cursor_pos += s.size();
+                       }
+               } else {
+                       // replace text
+
+                       core::stringw s = Text.subString(0, realmbgn);
+                       s.append(p);
+                       s.append(Text.subString(realmend, Text.size() - realmend));
+
+                       if (!m_max || s.size() <= m_max) {
+                               Text = s;
+                               s = p;
+                               m_cursor_pos = realmbgn + s.size();
+                       }
+               }
+       }
+
+       mark_begin = 0;
+       mark_end = 0;
+       return true;
+}
+
+bool GUIEditBox::onKeyBack(const SEvent &event, s32 &mark_begin, s32 &mark_end)
+{
+       if (!isEnabled() || Text.empty())
+               return false;
+
+       core::stringw s;
+
+       if (m_mark_begin != m_mark_end) {
+               // delete marked text
+               const s32 realmbgn =
+                               m_mark_begin < m_mark_end ? m_mark_begin : m_mark_end;
+               const s32 realmend =
+                               m_mark_begin < m_mark_end ? m_mark_end : m_mark_begin;
+
+               s = Text.subString(0, realmbgn);
+               s.append(Text.subString(realmend, Text.size() - realmend));
+               Text = s;
+
+               m_cursor_pos = realmbgn;
+       } else {
+               // delete text behind cursor
+               if (m_cursor_pos > 0)
+                       s = Text.subString(0, m_cursor_pos - 1);
+               else
+                       s = L"";
+               s.append(Text.subString(m_cursor_pos, Text.size() - m_cursor_pos));
+               Text = s;
+               --m_cursor_pos;
+       }
+
+       if (m_cursor_pos < 0)
+               m_cursor_pos = 0;
+       m_blink_start_time = porting::getTimeMs(); // os::Timer::getTime();
+       mark_begin = 0;
+       mark_end = 0;
+       return true;
+}
+
+bool GUIEditBox::onKeyDelete(const SEvent &event, s32 &mark_begin, s32 &mark_end)
+{
+       if (!isEnabled() || Text.empty())
+               return false;
+
+       core::stringw s;
+
+       if (m_mark_begin != m_mark_end) {
+               // delete marked text
+               const s32 realmbgn =
+                               m_mark_begin < m_mark_end ? m_mark_begin : m_mark_end;
+               const s32 realmend =
+                               m_mark_begin < m_mark_end ? m_mark_end : m_mark_begin;
+
+               s = Text.subString(0, realmbgn);
+               s.append(Text.subString(realmend, Text.size() - realmend));
+               Text = s;
+
+               m_cursor_pos = realmbgn;
+       } else {
+               // delete text before cursor
+               s = Text.subString(0, m_cursor_pos);
+               s.append(Text.subString(
+                               m_cursor_pos + 1, Text.size() - m_cursor_pos - 1));
+               Text = s;
+       }
+
+       if (m_cursor_pos > (s32)Text.size())
+               m_cursor_pos = (s32)Text.size();
+
+       m_blink_start_time = porting::getTimeMs(); // os::Timer::getTime();
+       mark_begin = 0;
+       mark_end = 0;
+       return true;
+}
+
+void GUIEditBox::inputChar(wchar_t c)
+{
+       if (c == 0)
+               return;
+       core::stringw s(&c, 1);
+       inputString(s);
+}
+
+void GUIEditBox::inputString(const core::stringw &str)
+{
+       if (!isEnabled() || !m_writable)
+               return;
+
+       u32 len = str.size();
+       if (Text.size()+len <= m_max || m_max == 0) {
+               core::stringw s;
+               if (m_mark_begin != m_mark_end) {
+                       // replace marked text
+                       s32 real_begin = m_mark_begin < m_mark_end ? m_mark_begin : m_mark_end;
+                       s32 real_end = m_mark_begin < m_mark_end ? m_mark_end : m_mark_begin;
+
+                       s = Text.subString(0, real_begin);
+                       s.append(str);
+                       s.append(Text.subString(real_end, Text.size() - real_end));
+                       Text = s;
+                       m_cursor_pos = real_begin + len;
+               } else {
+                       // append string
+                       s = Text.subString(0, m_cursor_pos);
+                       s.append(str);
+                       s.append(Text.subString(m_cursor_pos,
+                                       Text.size() - m_cursor_pos));
+                       Text = s;
+                       m_cursor_pos += len;
+               }
+
+               m_blink_start_time = porting::getTimeMs();
+               setTextMarkers(0, 0);
+       }
+
+       breakText();
+       sendGuiEvent(EGET_EDITBOX_CHANGED);
+       calculateScrollPos();
+}
+
+bool GUIEditBox::processMouse(const SEvent &event)
+{
+       switch (event.MouseInput.Event) {
+       case irr::EMIE_LMOUSE_LEFT_UP:
+               if (Environment->hasFocus(this)) {
+                       m_cursor_pos = getCursorPos(
+                                       event.MouseInput.X, event.MouseInput.Y);
+                       if (m_mouse_marking) {
+                               setTextMarkers(m_mark_begin, m_cursor_pos);
+                       }
+                       m_mouse_marking = false;
+                       calculateScrollPos();
+                       return true;
+               }
+               break;
+       case irr::EMIE_MOUSE_MOVED: {
+               if (m_mouse_marking) {
+                       m_cursor_pos = getCursorPos(
+                                       event.MouseInput.X, event.MouseInput.Y);
+                       setTextMarkers(m_mark_begin, m_cursor_pos);
+                       calculateScrollPos();
+                       return true;
+               }
+       } break;
+       case EMIE_LMOUSE_PRESSED_DOWN:
+
+               if (!Environment->hasFocus(this)) {
+                       m_blink_start_time = porting::getTimeMs();
+                       m_mouse_marking = true;
+                       m_cursor_pos = getCursorPos(
+                                       event.MouseInput.X, event.MouseInput.Y);
+                       setTextMarkers(m_cursor_pos, m_cursor_pos);
+                       calculateScrollPos();
+                       return true;
+               } else {
+                       if (!AbsoluteClippingRect.isPointInside(core::position2d<s32>(
+                                           event.MouseInput.X, event.MouseInput.Y))) {
+                               return false;
+                       } else {
+                               // move cursor
+                               m_cursor_pos = getCursorPos(
+                                               event.MouseInput.X, event.MouseInput.Y);
+
+                               s32 newMarkBegin = m_mark_begin;
+                               if (!m_mouse_marking)
+                                       newMarkBegin = m_cursor_pos;
+
+                               m_mouse_marking = true;
+                               setTextMarkers(newMarkBegin, m_cursor_pos);
+                               calculateScrollPos();
+                               return true;
+                       }
+               }
+       case EMIE_MOUSE_WHEEL:
+               if (m_vscrollbar && m_vscrollbar->isVisible()) {
+                       s32 pos = m_vscrollbar->getPos();
+                       s32 step = m_vscrollbar->getSmallStep();
+                       m_vscrollbar->setPos(pos - event.MouseInput.Wheel * step);
+                       return true;
+               }
+               break;
+       default:
+               break;
+       }
+
+       return false;
+}
+
+s32 GUIEditBox::getLineFromPos(s32 pos)
+{
+       if (!m_word_wrap && !m_multiline)
+               return 0;
+
+       s32 i = 0;
+       while (i < (s32)m_broken_text_positions.size()) {
+               if (m_broken_text_positions[i] > pos)
+                       return i - 1;
+               ++i;
+       }
+       return (s32)m_broken_text_positions.size() - 1;
+}
+
+void GUIEditBox::updateVScrollBar()
+{
+       if (!m_vscrollbar) {
+               return;
+       }
+
+       // OnScrollBarChanged(...)
+       if (m_vscrollbar->getPos() != m_vscroll_pos) {
+               s32 deltaScrollY = m_vscrollbar->getPos() - m_vscroll_pos;
+               m_current_text_rect.UpperLeftCorner.Y -= deltaScrollY;
+               m_current_text_rect.LowerRightCorner.Y -= deltaScrollY;
+
+               s32 scrollymax = getTextDimension().Height - m_frame_rect.getHeight();
+               if (scrollymax != m_vscrollbar->getMax()) {
+                       // manage a newline or a deleted line
+                       m_vscrollbar->setMax(scrollymax);
+                       m_vscrollbar->setPageSize(s32(getTextDimension().Height));
+                       calculateScrollPos();
+               } else {
+                       // manage a newline or a deleted line
+                       m_vscroll_pos = m_vscrollbar->getPos();
+               }
+       }
+
+       // check if a vertical scrollbar is needed ?
+       if (getTextDimension().Height > (u32)m_frame_rect.getHeight()) {
+               m_frame_rect.LowerRightCorner.X -= m_scrollbar_width;
+
+               s32 scrollymax = getTextDimension().Height - m_frame_rect.getHeight();
+               if (scrollymax != m_vscrollbar->getMax()) {
+                       m_vscrollbar->setMax(scrollymax);
+                       m_vscrollbar->setPageSize(s32(getTextDimension().Height));
+               }
+
+               if (!m_vscrollbar->isVisible()) {
+                       m_vscrollbar->setVisible(true);
+               }
+       } else {
+               if (m_vscrollbar->isVisible()) {
+                       m_vscrollbar->setVisible(false);
+                       m_vscroll_pos = 0;
+                       m_vscrollbar->setPos(0);
+                       m_vscrollbar->setMax(1);
+                       m_vscrollbar->setPageSize(s32(getTextDimension().Height));
+               }
+       }
+}
+
+void GUIEditBox::deserializeAttributes(
+               io::IAttributes *in, io::SAttributeReadWriteOptions *options = 0)
+{
+       IGUIEditBox::deserializeAttributes(in, options);
+
+       setOverrideColor(in->getAttributeAsColor("OverrideColor"));
+       enableOverrideColor(in->getAttributeAsBool("OverrideColorEnabled"));
+       setMax(in->getAttributeAsInt("MaxChars"));
+       setWordWrap(in->getAttributeAsBool("WordWrap"));
+       setMultiLine(in->getAttributeAsBool("MultiLine"));
+       setAutoScroll(in->getAttributeAsBool("AutoScroll"));
+       core::stringw ch = in->getAttributeAsStringW("PasswordChar");
+
+       if (ch.empty())
+               setPasswordBox(in->getAttributeAsBool("PasswordBox"));
+       else
+               setPasswordBox(in->getAttributeAsBool("PasswordBox"), ch[0]);
+
+       setTextAlignment((EGUI_ALIGNMENT)in->getAttributeAsEnumeration(
+                                        "HTextAlign", GUIAlignmentNames),
+                       (EGUI_ALIGNMENT)in->getAttributeAsEnumeration(
+                                       "VTextAlign", GUIAlignmentNames));
+
+       setWritable(in->getAttributeAsBool("Writable"));
+       // setOverrideFont(in->getAttributeAsFont("OverrideFont"));
+}
+
+//! Writes attributes of the element.
+void GUIEditBox::serializeAttributes(
+               io::IAttributes *out, io::SAttributeReadWriteOptions *options = 0) const
+{
+       // IGUIEditBox::serializeAttributes(out,options);
+
+       out->addBool("OverrideColorEnabled", m_override_color_enabled);
+       out->addColor("OverrideColor", m_override_color);
+       // out->addFont("OverrideFont",m_override_font);
+       out->addInt("MaxChars", m_max);
+       out->addBool("WordWrap", m_word_wrap);
+       out->addBool("MultiLine", m_multiline);
+       out->addBool("AutoScroll", m_autoscroll);
+       out->addBool("PasswordBox", m_passwordbox);
+       core::stringw ch = L" ";
+       ch[0] = m_passwordchar;
+       out->addString("PasswordChar", ch.c_str());
+       out->addEnum("HTextAlign", m_halign, GUIAlignmentNames);
+       out->addEnum("VTextAlign", m_valign, GUIAlignmentNames);
+       out->addBool("Writable", m_writable);
+
+       IGUIEditBox::serializeAttributes(out, options);
+}