aboutsummaryrefslogtreecommitdiff
path: root/src/intlGUIEditBox.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/intlGUIEditBox.cpp')
-rw-r--r--src/intlGUIEditBox.cpp1508
1 files changed, 0 insertions, 1508 deletions
diff --git a/src/intlGUIEditBox.cpp b/src/intlGUIEditBox.cpp
deleted file mode 100644
index 32cca4866..000000000
--- a/src/intlGUIEditBox.cpp
+++ /dev/null
@@ -1,1508 +0,0 @@
-// 11.11.2011 11:11 ValkaTR
-//
-// This is a copy of intlGUIEditBox from the irrlicht, but with a
-// fix in the OnEvent function, which doesn't allowed input of
-// other keyboard layouts than latin-1
-//
-// Characters like: ä ö ü õ ы й ю я ъ № € ° ...
-//
-// This fix is only needed for linux, because of a bug
-// in the CIrrDeviceLinux.cpp:1014-1015 of the irrlicht
-//
-// Also locale in the programm should not be changed to
-// a "C", "POSIX" or whatever, it should be set to "",
-// or XLookupString will return nothing for the international
-// characters.
-//
-// From the "man setlocale":
-//
-// On startup of the main program, the portable "C" locale
-// is selected as default. A program may be made
-// portable to all locales by calling:
-//
-// setlocale(LC_ALL, "");
-//
-// after program initialization....
-//
-
-// Copyright (C) 2002-2013 Nikolaus Gebhardt
-// This file is part of the "Irrlicht Engine".
-// For conditions of distribution and use, see copyright notice in irrlicht.h
-
-#include "intlGUIEditBox.h"
-
-#ifdef _IRR_COMPILE_WITH_GUI_
-
-#include "IGUISkin.h"
-#include "IGUIEnvironment.h"
-#include "IGUIFont.h"
-#include "IVideoDriver.h"
-//#include "rect.h"
-//#include "irrlicht/os.cpp"
-#include "porting.h"
-//#include "Keycodes.h"
-
-/*
- todo:
- optional scrollbars
- ctrl+left/right to select word
- double click/ctrl click: word select + drag to select whole words, triple click to select line
- optional? dragging selected text
- numerical
-*/
-
-namespace irr
-{
-namespace gui
-{
-
-//! constructor
-intlGUIEditBox::intlGUIEditBox(const wchar_t* text, bool border,
- IGUIEnvironment* environment, IGUIElement* parent, s32 id,
- const core::rect<s32>& rectangle)
- : IGUIEditBox(environment, parent, id, rectangle), MouseMarking(false),
- Border(border), OverrideColorEnabled(false), MarkBegin(0), MarkEnd(0),
- OverrideColor(video::SColor(101,255,255,255)), OverrideFont(0), LastBreakFont(0),
- Operator(0), BlinkStartTime(0), CursorPos(0), HScrollPos(0), VScrollPos(0), Max(0),
- WordWrap(false), MultiLine(false), AutoScroll(true), PasswordBox(false),
- PasswordChar(L'*'), HAlign(EGUIA_UPPERLEFT), VAlign(EGUIA_CENTER),
- CurrentTextRect(0,0,1,1), FrameRect(rectangle)
-{
- #ifdef _DEBUG
- setDebugName("intlintlGUIEditBox");
- #endif
-
- Text = text;
-
- if (Environment)
- Operator = Environment->getOSOperator();
-
- if (Operator)
- Operator->grab();
-
- // this element can be tabbed to
- setTabStop(true);
- setTabOrder(-1);
-
- IGUISkin *skin = 0;
- if (Environment)
- skin = Environment->getSkin();
- if (Border && skin)
- {
- FrameRect.UpperLeftCorner.X += skin->getSize(EGDS_TEXT_DISTANCE_X)+1;
- FrameRect.UpperLeftCorner.Y += skin->getSize(EGDS_TEXT_DISTANCE_Y)+1;
- FrameRect.LowerRightCorner.X -= skin->getSize(EGDS_TEXT_DISTANCE_X)+1;
- FrameRect.LowerRightCorner.Y -= skin->getSize(EGDS_TEXT_DISTANCE_Y)+1;
- }
-
- breakText();
-
- calculateScrollPos();
-}
-
-
-//! destructor
-intlGUIEditBox::~intlGUIEditBox()
-{
- if (OverrideFont)
- OverrideFont->drop();
-
- if (Operator)
- Operator->drop();
-}
-
-
-//! Sets another skin independent font.
-void intlGUIEditBox::setOverrideFont(IGUIFont* font)
-{
- if (OverrideFont == font)
- return;
-
- if (OverrideFont)
- OverrideFont->drop();
-
- OverrideFont = font;
-
- if (OverrideFont)
- OverrideFont->grab();
-
- breakText();
-}
-
-IGUIFont * intlGUIEditBox::getOverrideFont() const
-{
- return OverrideFont;
-}
-
-//! Get the font which is used right now for drawing
-IGUIFont* intlGUIEditBox::getActiveFont() const
-{
- if ( OverrideFont )
- return OverrideFont;
- IGUISkin* skin = Environment->getSkin();
- if (skin)
- return skin->getFont();
- return 0;
-}
-
-//! Sets another color for the text.
-void intlGUIEditBox::setOverrideColor(video::SColor color)
-{
- OverrideColor = color;
- OverrideColorEnabled = true;
-}
-
-video::SColor intlGUIEditBox::getOverrideColor() const
-{
- return OverrideColor;
-}
-
-//! Turns the border on or off
-void intlGUIEditBox::setDrawBorder(bool border)
-{
- Border = border;
-}
-
-//! Sets whether to draw the background
-void intlGUIEditBox::setDrawBackground(bool draw)
-{
-}
-
-//! Sets if the text should use the overide color or the color in the gui skin.
-void intlGUIEditBox::enableOverrideColor(bool enable)
-{
- OverrideColorEnabled = enable;
-}
-
-bool intlGUIEditBox::isOverrideColorEnabled() const
-{
- _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
- return OverrideColorEnabled;
-}
-
-//! Enables or disables word wrap
-void intlGUIEditBox::setWordWrap(bool enable)
-{
- WordWrap = enable;
- breakText();
-}
-
-
-void intlGUIEditBox::updateAbsolutePosition()
-{
- core::rect<s32> oldAbsoluteRect(AbsoluteRect);
- IGUIElement::updateAbsolutePosition();
- if ( oldAbsoluteRect != AbsoluteRect )
- {
- breakText();
- }
-}
-
-
-//! Checks if word wrap is enabled
-bool intlGUIEditBox::isWordWrapEnabled() const
-{
- _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
- return WordWrap;
-}
-
-
-//! Enables or disables newlines.
-void intlGUIEditBox::setMultiLine(bool enable)
-{
- MultiLine = enable;
-}
-
-
-//! Checks if multi line editing is enabled
-bool intlGUIEditBox::isMultiLineEnabled() const
-{
- _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
- return MultiLine;
-}
-
-
-void intlGUIEditBox::setPasswordBox(bool passwordBox, wchar_t passwordChar)
-{
- PasswordBox = passwordBox;
- if (PasswordBox)
- {
- PasswordChar = passwordChar;
- setMultiLine(false);
- setWordWrap(false);
- BrokenText.clear();
- }
-}
-
-
-bool intlGUIEditBox::isPasswordBox() const
-{
- _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
- return PasswordBox;
-}
-
-
-//! Sets text justification
-void intlGUIEditBox::setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT vertical)
-{
- HAlign = horizontal;
- VAlign = vertical;
-}
-
-
-//! called if an event happened.
-bool intlGUIEditBox::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)
- {
- MouseMarking = false;
- setTextMarkers(0,0);
- }
- }
- break;
- case EET_KEY_INPUT_EVENT:
- {
-#if defined(linux)
- // ################################################################
- // ValkaTR:
- // This part is the difference from the original intlGUIEditBox
- // It converts UTF-8 character into a UCS-2 (wchar_t)
- wchar_t wc = L'_';
- mbtowc( &wc, (char *) &event.KeyInput.Char, sizeof(event.KeyInput.Char) );
-
- //printf( "char: %lc (%u) \r\n", wc, wc );
-
- SEvent irrevent(event);
- irrevent.KeyInput.Char = wc;
- // ################################################################
-
- if (processKey(irrevent))
- return true;
-#else
- if (processKey(event))
- return true;
-#endif // defined(linux)
-
- break;
- }
- case EET_MOUSE_INPUT_EVENT:
- if (processMouse(event))
- return true;
- break;
- default:
- break;
- }
- }
-
- return IGUIElement::OnEvent(event);
-}
-
-
-bool intlGUIEditBox::processKey(const SEvent& event)
-{
- if (!event.KeyInput.PressedDown)
- return false;
-
- bool textChanged = false;
- s32 newMarkBegin = MarkBegin;
- s32 newMarkEnd = MarkEnd;
-
- // 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
- newMarkBegin = 0;
- newMarkEnd = Text.size();
- break;
- case KEY_KEY_C:
- // copy to clipboard
- if (!PasswordBox && Operator && MarkBegin != MarkEnd)
- {
- const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd;
- const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin;
-
- core::stringc s;
- s = Text.subString(realmbgn, realmend - realmbgn).c_str();
- Operator->copyToClipboard(s.c_str());
- }
- break;
- case KEY_KEY_X:
- // cut to the clipboard
- if (!PasswordBox && Operator && MarkBegin != MarkEnd)
- {
- const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd;
- const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin;
-
- // copy
- core::stringc sc;
- sc = Text.subString(realmbgn, realmend - realmbgn).c_str();
- Operator->copyToClipboard(sc.c_str());
-
- if (IsEnabled)
- {
- // delete
- core::stringw s;
- s = Text.subString(0, realmbgn);
- s.append( Text.subString(realmend, Text.size()-realmend) );
- Text = s;
-
- CursorPos = realmbgn;
- newMarkBegin = 0;
- newMarkEnd = 0;
- textChanged = true;
- }
- }
- break;
- case KEY_KEY_V:
- if ( !IsEnabled )
- break;
-
- // paste from the clipboard
- if (Operator)
- {
- const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd;
- const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin;
-
- // add new character
- const c8* p = Operator->getTextFromClipboard();
- if (p)
- {
- if (MarkBegin == MarkEnd)
- {
- // insert text
- core::stringw s = Text.subString(0, CursorPos);
- s.append(p);
- s.append( Text.subString(CursorPos, Text.size()-CursorPos) );
-
- if (!Max || s.size()<=Max) // thx to Fish FH for fix
- {
- Text = s;
- s = p;
- CursorPos += s.size();
- }
- }
- else
- {
- // replace text
-
- core::stringw s = Text.subString(0, realmbgn);
- s.append(p);
- s.append( Text.subString(realmend, Text.size()-realmend) );
-
- if (!Max || s.size()<=Max) // thx to Fish FH for fix
- {
- Text = s;
- s = p;
- CursorPos = realmbgn + s.size();
- }
- }
- }
-
- newMarkBegin = 0;
- newMarkEnd = 0;
- textChanged = true;
- }
- break;
- case KEY_HOME:
- // move/highlight to start of text
- if (event.KeyInput.Shift)
- {
- newMarkEnd = CursorPos;
- newMarkBegin = 0;
- CursorPos = 0;
- }
- else
- {
- CursorPos = 0;
- newMarkBegin = 0;
- newMarkEnd = 0;
- }
- break;
- case KEY_END:
- // move/highlight to end of text
- if (event.KeyInput.Shift)
- {
- newMarkBegin = CursorPos;
- newMarkEnd = Text.size();
- CursorPos = 0;
- }
- else
- {
- CursorPos = Text.size();
- newMarkBegin = 0;
- newMarkEnd = 0;
- }
- break;
- default:
- return false;
- }
- }
- // default keyboard handling
- else
- switch(event.KeyInput.Key)
- {
- case KEY_END:
- {
- s32 p = Text.size();
- if (WordWrap || MultiLine)
- {
- p = getLineFromPos(CursorPos);
- p = BrokenTextPositions[p] + (s32)BrokenText[p].size();
- if (p > 0 && (Text[p-1] == L'\r' || Text[p-1] == L'\n' ))
- p-=1;
- }
-
- if (event.KeyInput.Shift)
- {
- if (MarkBegin == MarkEnd)
- newMarkBegin = CursorPos;
-
- newMarkEnd = p;
- }
- else
- {
- newMarkBegin = 0;
- newMarkEnd = 0;
- }
- CursorPos = p;
- BlinkStartTime = porting::getTimeMs();
- }
- break;
- case KEY_HOME:
- {
-
- s32 p = 0;
- if (WordWrap || MultiLine)
- {
- p = getLineFromPos(CursorPos);
- p = BrokenTextPositions[p];
- }
-
- if (event.KeyInput.Shift)
- {
- if (MarkBegin == MarkEnd)
- newMarkBegin = CursorPos;
- newMarkEnd = p;
- }
- else
- {
- newMarkBegin = 0;
- newMarkEnd = 0;
- }
- CursorPos = p;
- BlinkStartTime = porting::getTimeMs();
- }
- break;
- case KEY_RETURN:
- if (MultiLine)
- {
- inputChar(L'\n');
- return true;
- }
- else
- {
- sendGuiEvent( EGET_EDITBOX_ENTER );
- }
- break;
- case KEY_LEFT:
-
- if (event.KeyInput.Shift)
- {
- if (CursorPos > 0)
- {
- if (MarkBegin == MarkEnd)
- newMarkBegin = CursorPos;
-
- newMarkEnd = CursorPos-1;
- }
- }
- else
- {
- newMarkBegin = 0;
- newMarkEnd = 0;
- }
-
- if (CursorPos > 0) CursorPos--;
- BlinkStartTime = porting::getTimeMs();
- break;
-
- case KEY_RIGHT:
- if (event.KeyInput.Shift)
- {
- if (Text.size() > (u32)CursorPos)
- {
- if (MarkBegin == MarkEnd)
- newMarkBegin = CursorPos;
-
- newMarkEnd = CursorPos+1;
- }
- }
- else
- {
- newMarkBegin = 0;
- newMarkEnd = 0;
- }
-
- if (Text.size() > (u32)CursorPos) CursorPos++;
- BlinkStartTime = porting::getTimeMs();
- break;
- case KEY_UP:
- if (MultiLine || (WordWrap && BrokenText.size() > 1) )
- {
- s32 lineNo = getLineFromPos(CursorPos);
- s32 mb = (MarkBegin == MarkEnd) ? CursorPos : (MarkBegin > MarkEnd ? MarkBegin : MarkEnd);
- if (lineNo > 0)
- {
- s32 cp = CursorPos - BrokenTextPositions[lineNo];
- if ((s32)BrokenText[lineNo-1].size() < cp)
- CursorPos = BrokenTextPositions[lineNo-1] + (s32)BrokenText[lineNo-1].size()-1;
- else
- CursorPos = BrokenTextPositions[lineNo-1] + cp;
- }
-
- if (event.KeyInput.Shift)
- {
- newMarkBegin = mb;
- newMarkEnd = CursorPos;
- }
- else
- {
- newMarkBegin = 0;
- newMarkEnd = 0;
- }
-
- }
- else
- {
- return false;
- }
- break;
- case KEY_DOWN:
- if (MultiLine || (WordWrap && BrokenText.size() > 1) )
- {
- s32 lineNo = getLineFromPos(CursorPos);
- s32 mb = (MarkBegin == MarkEnd) ? CursorPos : (MarkBegin < MarkEnd ? MarkBegin : MarkEnd);
- if (lineNo < (s32)BrokenText.size()-1)
- {
- s32 cp = CursorPos - BrokenTextPositions[lineNo];
- if ((s32)BrokenText[lineNo+1].size() < cp)
- CursorPos = BrokenTextPositions[lineNo+1] + BrokenText[lineNo+1].size()-1;
- else
- CursorPos = BrokenTextPositions[lineNo+1] + cp;
- }
-
- if (event.KeyInput.Shift)
- {
- newMarkBegin = mb;
- newMarkEnd = CursorPos;
- }
- else
- {
- newMarkBegin = 0;
- newMarkEnd = 0;
- }
-
- }
- else
- {
- return false;
- }
- break;
-
- case KEY_BACK:
- if ( !this->IsEnabled )
- break;
-
- if (Text.size())
- {
- core::stringw s;
-
- if (MarkBegin != MarkEnd)
- {
- // delete marked text
- const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd;
- const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin;
-
- s = Text.subString(0, realmbgn);
- s.append( Text.subString(realmend, Text.size()-realmend) );
- Text = s;
-
- CursorPos = realmbgn;
- }
- else
- {
- // delete text behind cursor
- if (CursorPos>0)
- s = Text.subString(0, CursorPos-1);
- else
- s = L"";
- s.append( Text.subString(CursorPos, Text.size()-CursorPos) );
- Text = s;
- --CursorPos;
- }
-
- if (CursorPos < 0)
- CursorPos = 0;
- BlinkStartTime = porting::getTimeMs();
- newMarkBegin = 0;
- newMarkEnd = 0;
- textChanged = true;
- }
- break;
- case KEY_DELETE:
- if ( !this->IsEnabled )
- break;
-
- if (Text.size() != 0)
- {
- core::stringw s;
-
- if (MarkBegin != MarkEnd)
- {
- // delete marked text
- const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd;
- const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin;
-
- s = Text.subString(0, realmbgn);
- s.append( Text.subString(realmend, Text.size()-realmend) );
- Text = s;
-
- CursorPos = realmbgn;
- }
- else
- {
- // delete text before cursor
- s = Text.subString(0, CursorPos);
- s.append( Text.subString(CursorPos+1, Text.size()-CursorPos-1) );
- Text = s;
- }
-
- if (CursorPos > (s32)Text.size())
- CursorPos = (s32)Text.size();
-
- BlinkStartTime = porting::getTimeMs();
- newMarkBegin = 0;
- newMarkEnd = 0;
- textChanged = true;
- }
- 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( newMarkBegin, newMarkEnd );
-
- // break the text if it has changed
- if (textChanged)
- {
- breakText();
- sendGuiEvent(EGET_EDITBOX_CHANGED);
- }
-
- calculateScrollPos();
-
- return true;
-}
-
-
-//! draws the element and its children
-void intlGUIEditBox::draw()
-{
- if (!IsVisible)
- return;
-
- const bool focus = Environment->hasFocus(this);
-
- IGUISkin* skin = Environment->getSkin();
- if (!skin)
- return;
-
- FrameRect = AbsoluteRect;
-
- // draw the border
-
- if (Border)
- {
- skin->draw3DSunkenPane(this, skin->getColor(EGDC_WINDOW),
- false, true, FrameRect, &AbsoluteClippingRect);
-
- FrameRect.UpperLeftCorner.X += skin->getSize(EGDS_TEXT_DISTANCE_X)+1;
- FrameRect.UpperLeftCorner.Y += skin->getSize(EGDS_TEXT_DISTANCE_Y)+1;
- FrameRect.LowerRightCorner.X -= skin->getSize(EGDS_TEXT_DISTANCE_X)+1;
- FrameRect.LowerRightCorner.Y -= skin->getSize(EGDS_TEXT_DISTANCE_Y)+1;
- }
- core::rect<s32> localClipRect = FrameRect;
- localClipRect.clipAgainst(AbsoluteClippingRect);
-
- // draw the text
-
- IGUIFont* font = OverrideFont;
- if (!OverrideFont)
- font = skin->getFont();
-
- s32 cursorLine = 0;
- s32 charcursorpos = 0;
-
- if (font)
- {
- if (LastBreakFont != font)
- {
- breakText();
- }
-
- // calculate cursor pos
-
- core::stringw *txtLine = &Text;
- s32 startPos = 0;
-
- core::stringw s, s2;
-
- // get mark position
- const bool ml = (!PasswordBox && (WordWrap || MultiLine));
- const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd;
- const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin;
- const s32 hlineStart = ml ? getLineFromPos(realmbgn) : 0;
- const s32 hlineCount = ml ? getLineFromPos(realmend) - hlineStart + 1 : 1;
- const s32 lineCount = ml ? BrokenText.size() : 1;
-
- // Save the override color information.
- // Then, alter it if the edit box is disabled.
- const bool prevOver = OverrideColorEnabled;
- const video::SColor prevColor = OverrideColor;
-
- if (Text.size())
- {
- if (!IsEnabled && !OverrideColorEnabled)
- {
- OverrideColorEnabled = true;
- OverrideColor = skin->getColor(EGDC_GRAY_TEXT);
- }
-
- for (s32 i=0; i < lineCount; ++i)
- {
- setTextRect(i);
-
- // clipping test - don't draw anything outside the visible area
- core::rect<s32> c = localClipRect;
- c.clipAgainst(CurrentTextRect);
- if (!c.isValid())
- continue;
-
- // get current line
- if (PasswordBox)
- {
- if (BrokenText.size() != 1)
- {
- BrokenText.clear();
- BrokenText.push_back(core::stringw());
- }
- if (BrokenText[0].size() != Text.size())
- {
- BrokenText[0] = Text;
- for (u32 q = 0; q < Text.size(); ++q)
- {
- BrokenText[0] [q] = PasswordChar;
- }
- }
- txtLine = &BrokenText[0];
- startPos = 0;
- }
- else
- {
- txtLine = ml ? &BrokenText[i] : &Text;
- startPos = ml ? BrokenTextPositions[i] : 0;
- }
-
-
- // draw normal text
- font->draw(txtLine->c_str(), CurrentTextRect,
- OverrideColorEnabled ? OverrideColor : skin->getColor(EGDC_BUTTON_TEXT),
- false, true, &localClipRect);
-
- // draw mark and marked text
- if (focus && MarkBegin != MarkEnd && i >= hlineStart && i < hlineStart + hlineCount)
- {
-
- s32 mbegin = 0, mend = 0;
- s32 lineStartPos = 0, lineEndPos = txtLine->size();
-
- if (i == hlineStart)
- {
- // highlight start is on this line
- s = txtLine->subString(0, realmbgn - startPos);
- mbegin = font->getDimension(s.c_str()).Width;
-
- // deal with kerning
- mbegin += font->getKerningWidth(
- &((*txtLine)[realmbgn - startPos]),
- realmbgn - startPos > 0 ? &((*txtLine)[realmbgn - startPos - 1]) : 0);
-
- lineStartPos = realmbgn - startPos;
- }
- if (i == hlineStart + hlineCount - 1)
- {
- // highlight end is on this line
- s2 = txtLine->subString(0, realmend - startPos);
- mend = font->getDimension(s2.c_str()).Width;
- lineEndPos = (s32)s2.size();
- }
- else
- mend = font->getDimension(txtLine->c_str()).Width;
-
- CurrentTextRect.UpperLeftCorner.X += mbegin;
- CurrentTextRect.LowerRightCorner.X = CurrentTextRect.UpperLeftCorner.X + mend - mbegin;
-
- // draw mark
- skin->draw2DRectangle(this, skin->getColor(EGDC_HIGH_LIGHT), CurrentTextRect, &localClipRect);
-
- // draw marked text
- s = txtLine->subString(lineStartPos, lineEndPos - lineStartPos);
-
- if (s.size())
- font->draw(s.c_str(), CurrentTextRect,
- OverrideColorEnabled ? OverrideColor : skin->getColor(EGDC_HIGH_LIGHT_TEXT),
- false, true, &localClipRect);
-
- }
- }
-
- // Return the override color information to its previous settings.
- OverrideColorEnabled = prevOver;
- OverrideColor = prevColor;
- }
-
- // draw cursor
-
- if (WordWrap || MultiLine)
- {
- cursorLine = getLineFromPos(CursorPos);
- txtLine = &BrokenText[cursorLine];
- startPos = BrokenTextPositions[cursorLine];
- }
- s = txtLine->subString(0,CursorPos-startPos);
- charcursorpos = font->getDimension(s.c_str()).Width +
- font->getKerningWidth(L"_", CursorPos-startPos > 0 ? &((*txtLine)[CursorPos-startPos-1]) : 0);
-
- if (focus && (porting::getTimeMs() - BlinkStartTime) % 700 < 350)
- {
- setTextRect(cursorLine);
- CurrentTextRect.UpperLeftCorner.X += charcursorpos;
-
- font->draw(L"_", CurrentTextRect,
- OverrideColorEnabled ? OverrideColor : skin->getColor(EGDC_BUTTON_TEXT),
- false, true, &localClipRect);
- }
- }
-
- // draw children
- IGUIElement::draw();
-}
-
-
-//! Sets the new caption of this element.
-void intlGUIEditBox::setText(const wchar_t* text)
-{
- Text = text;
- if (u32(CursorPos) > Text.size())
- CursorPos = Text.size();
- HScrollPos = 0;
- breakText();
-}
-
-
-//! Enables or disables automatic scrolling with cursor position
-//! \param enable: If set to true, the text will move around with the cursor position
-void intlGUIEditBox::setAutoScroll(bool enable)
-{
- AutoScroll = enable;
-}
-
-
-//! Checks to see if automatic scrolling is enabled
-//! \return true if automatic scrolling is enabled, false if not
-bool intlGUIEditBox::isAutoScrollEnabled() const
-{
- _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
- return AutoScroll;
-}
-
-
-//! Gets the area of the text in the edit box
-//! \return Returns the size in pixels of the text
-core::dimension2du intlGUIEditBox::getTextDimension()
-{
- core::rect<s32> ret;
-
- setTextRect(0);
- ret = CurrentTextRect;
-
- for (u32 i=1; i < BrokenText.size(); ++i)
- {
- setTextRect(i);
- ret.addInternalPoint(CurrentTextRect.UpperLeftCorner);
- ret.addInternalPoint(CurrentTextRect.LowerRightCorner);
- }
-
- return core::dimension2du(ret.getSize());
-}
-
-
-//! 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 intlGUIEditBox::setMax(u32 max)
-{
- Max = max;
-
- if (Text.size() > Max && Max != 0)
- Text = Text.subString(0, Max);
-}
-
-
-//! Returns maximum amount of characters, previously set by setMax();
-u32 intlGUIEditBox::getMax() const
-{
- return Max;
-}
-
-
-bool intlGUIEditBox::processMouse(const SEvent& event)
-{
- switch(event.MouseInput.Event)
- {
- case irr::EMIE_LMOUSE_LEFT_UP:
- if (Environment->hasFocus(this))
- {
- CursorPos = getCursorPos(event.MouseInput.X, event.MouseInput.Y);
- if (MouseMarking)
- {
- setTextMarkers( MarkBegin, CursorPos );
- }
- MouseMarking = false;
- calculateScrollPos();
- return true;
- }
- break;
- case irr::EMIE_MOUSE_MOVED:
- {
- if (MouseMarking)
- {
- CursorPos = getCursorPos(event.MouseInput.X, event.MouseInput.Y);
- setTextMarkers( MarkBegin, CursorPos );
- calculateScrollPos();
- return true;
- }
- }
- break;
- case EMIE_LMOUSE_PRESSED_DOWN:
- if (!Environment->hasFocus(this))
- {
- BlinkStartTime = porting::getTimeMs();
- MouseMarking = true;
- CursorPos = getCursorPos(event.MouseInput.X, event.MouseInput.Y);
- setTextMarkers(CursorPos, CursorPos );
- calculateScrollPos();
- return true;
- }
- else
- {
- if (!AbsoluteClippingRect.isPointInside(
- core::position2d<s32>(event.MouseInput.X, event.MouseInput.Y)))
- {
- return false;
- }
- else
- {
- // move cursor
- CursorPos = getCursorPos(event.MouseInput.X, event.MouseInput.Y);
-
- s32 newMarkBegin = MarkBegin;
- if (!MouseMarking)
- newMarkBegin = CursorPos;
-
- MouseMarking = true;
- setTextMarkers( newMarkBegin, CursorPos);
- calculateScrollPos();
- return true;
- }
- }
- default:
- break;
- }
-
- return false;
-}
-
-
-s32 intlGUIEditBox::getCursorPos(s32 x, s32 y)
-{
- IGUIFont* font = OverrideFont;
- IGUISkin* skin = Environment->getSkin();
- if (!OverrideFont)
- font = skin->getFont();
-
- const u32 lineCount = (WordWrap || MultiLine) ? BrokenText.size() : 1;
-
- core::stringw *txtLine=0;
- s32 startPos=0;
- x+=3;
-
- for (u32 i=0; i < lineCount; ++i)
- {
- setTextRect(i);
- if (i == 0 && y < CurrentTextRect.UpperLeftCorner.Y)
- y = CurrentTextRect.UpperLeftCorner.Y;
- if (i == lineCount - 1 && y > CurrentTextRect.LowerRightCorner.Y )
- y = CurrentTextRect.LowerRightCorner.Y;
-
- // is it inside this region?
- if (y >= CurrentTextRect.UpperLeftCorner.Y && y <= CurrentTextRect.LowerRightCorner.Y)
- {
- // we've found the clicked line
- txtLine = (WordWrap || MultiLine) ? &BrokenText[i] : &Text;
- startPos = (WordWrap || MultiLine) ? BrokenTextPositions[i] : 0;
- break;
- }
- }
-
- if (x < CurrentTextRect.UpperLeftCorner.X)
- x = CurrentTextRect.UpperLeftCorner.X;
-
- s32 idx = font->getCharacterFromPos(Text.c_str(), x - CurrentTextRect.UpperLeftCorner.X);
-
- // click was on or left of the line
- if (idx != -1)
- return idx + startPos;
-
- // click was off the right edge of the line, go to end.
- return txtLine->size() + startPos;
-}
-
-
-//! Breaks the single text line.
-void intlGUIEditBox::breakText()
-{
- IGUISkin* skin = Environment->getSkin();
-
- if ((!WordWrap && !MultiLine) || !skin)
- return;
-
- BrokenText.clear(); // need to reallocate :/
- BrokenTextPositions.set_used(0);
-
- IGUIFont* font = OverrideFont;
- if (!OverrideFont)
- font = skin->getFont();
-
- if (!font)
- return;
-
- LastBreakFont = font;
-
- core::stringw line;
- core::stringw word;
- core::stringw whitespace;
- s32 lastLineStart = 0;
- s32 size = Text.size();
- s32 length = 0;
- s32 elWidth = RelativeRect.getWidth() - 6;
- wchar_t c;
-
- for (s32 i=0; i<size; ++i)
- {
- c = Text[i];
- bool lineBreak = false;
-
- if (c == L'\r') // Mac or Windows breaks
- {
- lineBreak = true;
- c = ' ';
- if (Text[i+1] == L'\n') // Windows breaks
- {
- Text.erase(i+1);
- --size;
- }
- }
- else if (c == L'\n') // Unix breaks
- {
- lineBreak = true;
- c = ' ';
- }
-
- // don't break if we're not a multi-line edit box
- if (!MultiLine)
- lineBreak = false;
-
- if (c == L' ' || c == 0 || i == (size-1))
- {
- if (word.size())
- {
- // here comes the next whitespace, look if
- // we can break the last word to the next line.
- s32 whitelgth = font->getDimension(whitespace.c_str()).Width;
- s32 worldlgth = font->getDimension(word.c_str()).Width;
-
- if (WordWrap && length + worldlgth + whitelgth > elWidth)
- {
- // break to next line
- length = worldlgth;
- BrokenText.push_back(line);
- BrokenTextPositions.push_back(lastLineStart);
- lastLineStart = i - (s32)word.size();
- line = word;
- }
- else
- {
- // add word to line
- line += whitespace;
- line += word;
- length += whitelgth + worldlgth;
- }
-
- word = L"";
- whitespace = L"";
- }
-
- whitespace += c;
-
- // compute line break
- if (lineBreak)
- {
- line += whitespace;
- line += word;
- BrokenText.push_back(line);
- BrokenTextPositions.push_back(lastLineStart);
- lastLineStart = i+1;
- line = L"";
- word = L"";
- whitespace = L"";
- length = 0;
- }
- }
- else
- {
- // yippee this is a word..
- word += c;
- }
- }
-
- line += whitespace;
- line += word;
- BrokenText.push_back(line);
- BrokenTextPositions.push_back(lastLineStart);
-}
-
-
-void intlGUIEditBox::setTextRect(s32 line)
-{
- core::dimension2du d;
-
- IGUISkin* skin = Environment->getSkin();
- if (!skin)
- return;
-
- IGUIFont* font = OverrideFont ? OverrideFont : skin->getFont();
-
- if (!font)
- return;
-
- // get text dimension
- const u32 lineCount = (WordWrap || MultiLine) ? BrokenText.size() : 1;
- if (WordWrap || MultiLine)
- {
- d = font->getDimension(BrokenText[line].c_str());
- }
- else
- {
- d = font->getDimension(Text.c_str());
- d.Height = AbsoluteRect.getHeight();
- }
- d.Height += font->getKerningHeight();
-
- // justification
- switch (HAlign)
- {
- case EGUIA_CENTER:
- // align to h centre
- CurrentTextRect.UpperLeftCorner.X = (FrameRect.getWidth()/2) - (d.Width/2);
- CurrentTextRect.LowerRightCorner.X = (FrameRect.getWidth()/2) + (d.Width/2);
- break;
- case EGUIA_LOWERRIGHT:
- // align to right edge
- CurrentTextRect.UpperLeftCorner.X = FrameRect.getWidth() - d.Width;
- CurrentTextRect.LowerRightCorner.X = FrameRect.getWidth();
- break;
- default:
- // align to left edge
- CurrentTextRect.UpperLeftCorner.X = 0;
- CurrentTextRect.LowerRightCorner.X = d.Width;
-
- }
-
- switch (VAlign)
- {
- case EGUIA_CENTER:
- // align to v centre
- CurrentTextRect.UpperLeftCorner.Y =
- (FrameRect.getHeight()/2) - (lineCount*d.Height)/2 + d.Height*line;
- break;
- case EGUIA_LOWERRIGHT:
- // align to bottom edge
- CurrentTextRect.UpperLeftCorner.Y =
- FrameRect.getHeight() - lineCount*d.Height + d.Height*line;
- break;
- default:
- // align to top edge
- CurrentTextRect.UpperLeftCorner.Y = d.Height*line;
- break;
- }
-
- CurrentTextRect.UpperLeftCorner.X -= HScrollPos;
- CurrentTextRect.LowerRightCorner.X -= HScrollPos;
- CurrentTextRect.UpperLeftCorner.Y -= VScrollPos;
- CurrentTextRect.LowerRightCorner.Y = CurrentTextRect.UpperLeftCorner.Y + d.Height;
-
- CurrentTextRect += FrameRect.UpperLeftCorner;
-
-}
-
-
-s32 intlGUIEditBox::getLineFromPos(s32 pos)
-{
- if (!WordWrap && !MultiLine)
- return 0;
-
- s32 i=0;
- while (i < (s32)BrokenTextPositions.size())
- {
- if (BrokenTextPositions[i] > pos)
- return i-1;
- ++i;
- }
- return (s32)BrokenTextPositions.size() - 1;
-}
-
-
-void intlGUIEditBox::inputChar(wchar_t c)
-{
- if (!IsEnabled)
- return;
-
- if (c != 0)
- {
- if (Text.size() < Max || Max == 0)
- {
- core::stringw s;
-
- if (MarkBegin != MarkEnd)
- {
- // replace marked text
- const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd;
- const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin;
-
- s = Text.subString(0, realmbgn);
- s.append(c);
- s.append( Text.subString(realmend, Text.size()-realmend) );
- Text = s;
- CursorPos = realmbgn+1;
- }
- else
- {
- // add new character
- s = Text.subString(0, CursorPos);
- s.append(c);
- s.append( Text.subString(CursorPos, Text.size()-CursorPos) );
- Text = s;
- ++CursorPos;
- }
-
- BlinkStartTime = porting::getTimeMs();
- setTextMarkers(0, 0);
- }
- }
- breakText();
- sendGuiEvent(EGET_EDITBOX_CHANGED);
- calculateScrollPos();
-}
-
-
-void intlGUIEditBox::calculateScrollPos()
-{
- if (!AutoScroll)
- return;
-
- // calculate horizontal scroll position
- s32 cursLine = getLineFromPos(CursorPos);
- setTextRect(cursLine);
-
- // don't do horizontal scrolling when wordwrap is enabled.
- if (!WordWrap)
- {
- // get cursor position
- IGUISkin* skin = Environment->getSkin();
- if (!skin)
- return;
- IGUIFont* font = OverrideFont ? OverrideFont : skin->getFont();
- if (!font)
- return;
-
- core::stringw *txtLine = MultiLine ? &BrokenText[cursLine] : &Text;
- s32 cPos = MultiLine ? CursorPos - BrokenTextPositions[cursLine] : CursorPos;
-
- s32 cStart = CurrentTextRect.UpperLeftCorner.X + HScrollPos +
- font->getDimension(txtLine->subString(0, cPos).c_str()).Width;
-
- s32 cEnd = cStart + font->getDimension(L"_ ").Width;
-
- if (FrameRect.LowerRightCorner.X < cEnd)
- HScrollPos = cEnd - FrameRect.LowerRightCorner.X;
- else if (FrameRect.UpperLeftCorner.X > cStart)
- HScrollPos = cStart - FrameRect.UpperLeftCorner.X;
- else
- HScrollPos = 0;
-
- // todo: adjust scrollbar
- }
-
- // vertical scroll position
- if (FrameRect.LowerRightCorner.Y < CurrentTextRect.LowerRightCorner.Y + VScrollPos)
- VScrollPos = CurrentTextRect.LowerRightCorner.Y - FrameRect.LowerRightCorner.Y + VScrollPos;
-
- else if (FrameRect.UpperLeftCorner.Y > CurrentTextRect.UpperLeftCorner.Y + VScrollPos)
- VScrollPos = CurrentTextRect.UpperLeftCorner.Y - FrameRect.UpperLeftCorner.Y + VScrollPos;
- else
- VScrollPos = 0;
-
- // todo: adjust scrollbar
-}
-
-//! set text markers
-void intlGUIEditBox::setTextMarkers(s32 begin, s32 end)
-{
- if ( begin != MarkBegin || end != MarkEnd )
- {
- MarkBegin = begin;
- MarkEnd = end;
- sendGuiEvent(EGET_EDITBOX_MARKING_CHANGED);
- }
-}
-
-//! send some gui event to parent
-void intlGUIEditBox::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);
- }
-}
-
-//! Writes attributes of the element.
-void intlGUIEditBox::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const
-{
- // IGUIEditBox::serializeAttributes(out,options);
-
- out->addBool ("OverrideColorEnabled",OverrideColorEnabled );
- out->addColor ("OverrideColor", OverrideColor);
- // out->addFont("OverrideFont",OverrideFont);
- out->addInt ("MaxChars", Max);
- out->addBool ("WordWrap", WordWrap);
- out->addBool ("MultiLine", MultiLine);
- out->addBool ("AutoScroll", AutoScroll);
- out->addBool ("PasswordBox", PasswordBox);
- core::stringw ch = L" ";
- ch[0] = PasswordChar;
- out->addString("PasswordChar", ch.c_str());
- out->addEnum ("HTextAlign", HAlign, GUIAlignmentNames);
- out->addEnum ("VTextAlign", VAlign, GUIAlignmentNames);
-
- IGUIEditBox::serializeAttributes(out,options);
-}
-
-
-//! Reads attributes of the element
-void intlGUIEditBox::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.size())
- setPasswordBox(in->getAttributeAsBool("PasswordBox"));
- else
- setPasswordBox(in->getAttributeAsBool("PasswordBox"), ch[0]);
-
- setTextAlignment( (EGUI_ALIGNMENT) in->getAttributeAsEnumeration("HTextAlign", GUIAlignmentNames),
- (EGUI_ALIGNMENT) in->getAttributeAsEnumeration("VTextAlign", GUIAlignmentNames));
-
- // setOverrideFont(in->getAttributeAsFont("OverrideFont"));
-}
-
-
-} // end namespace gui
-} // end namespace irr
-
-#endif // _IRR_COMPILE_WITH_GUI_