From d7e374aed70507761239ae1ceb97e1ee7c73f584 Mon Sep 17 00:00:00 2001 From: darkrose Date: Mon, 17 Nov 2014 23:11:50 +1000 Subject: [PATCH] fix utf-8 and numpad in editboxes --- src/CMakeLists.txt | 4 + src/character_creator.cpp | 21 - src/game.cpp | 16 - src/gettext.h | 18 +- src/guiDeathScreen.cpp | 9 +- src/guiFormSpecMenu.cpp | 22 +- src/guiKeyChangeMenu.cpp | 11 - src/guiMainMenu.cpp | 59 +- src/guiMainMenu.h | 1 + src/guiMessageMenu.cpp | 2 - src/guiPasswordChange.cpp | 49 +- src/guiPauseMenu.cpp | 48 +- src/guiTextInputMenu.cpp | 21 +- src/intlGUIEditBox.cpp | 1538 +++++++++++++++++++++++++++++++++++++ src/intlGUIEditBox.h | 185 +++++ src/main.cpp | 6 - src/mapnode.cpp | 14 - 17 files changed, 1829 insertions(+), 195 deletions(-) create mode 100644 src/intlGUIEditBox.cpp create mode 100644 src/intlGUIEditBox.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 76ffe26..30a9c8b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -281,6 +281,10 @@ include_directories( ) if(USE_FREETYPE) + set(voxelands_SRCS + ${voxelands_SRCS} + intlGUIEditBox.cpp + ) include_directories( ${FREETYPE_INCLUDE_DIRS} ${CGUITTFONT_INCLUDE_DIR} diff --git a/src/character_creator.cpp b/src/character_creator.cpp index 832575d..dafdf63 100644 --- a/src/character_creator.cpp +++ b/src/character_creator.cpp @@ -55,7 +55,6 @@ GUICharDefMenu::GUICharDefMenu( fetchPlayerSkin(); - changeCtype(""); m_skintone_types["white"] = wgettext("White Skin"); m_skintone_types["red"] = wgettext("Red Skin"); m_skintone_types["green"] = wgettext("Green Skin"); @@ -115,7 +114,6 @@ GUICharDefMenu::GUICharDefMenu( m_shoes_types["leather"] = wgettext("Leather Shoes"); m_shoes_types["fur"] = wgettext("Fur Shoes"); m_shoes_types["canvas"] = wgettext("Canvas Shoes"); - changeCtype("C"); scene::ISceneManager* smgr = device->getSceneManager(); @@ -199,7 +197,6 @@ void GUICharDefMenu::regenerateGui(v2u32 screensize) DesiredRect = rect; recalculateAbsolutePosition(false); - changeCtype(""); { core::rect rect(0, 0, 230, 300); rect += leftside + v2s32(10, 220); @@ -229,7 +226,6 @@ void GUICharDefMenu::regenerateGui(v2u32 screensize) gui::IGUIStaticText *t = Environment->addStaticText(wgettext("Create Your Character"), rect, false, true, this, -1); t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT); } - //changeCtype("C"); // gender { core::rect rect(0, 0, 105, 30); @@ -268,14 +264,12 @@ void GUICharDefMenu::regenerateGui(v2u32 screensize) // skintone //185 - //changeCtype(""); { core::rect rect(0, 0, 160, 20); rect += rightside + v2s32(45, 170); gui::IGUIStaticText *t = Environment->addStaticText(m_skintone_types[m_parts["skintone"]].c_str(), rect, false, true, this, -1); t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT); } - //changeCtype("C"); { core::rect rect(0, 0, 30, 30); rect += rightside + v2s32(15, 165); @@ -289,14 +283,12 @@ void GUICharDefMenu::regenerateGui(v2u32 screensize) // face //220 - //changeCtype(""); { core::rect rect(0, 0, 160, 20); rect += rightside + v2s32(45, 205); gui::IGUIStaticText *t = Environment->addStaticText(m_face_types[m_parts["face"]].c_str(), rect, false, true, this, -1); t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT); } - //changeCtype("C"); { core::rect rect(0, 0, 30, 30); rect += rightside + v2s32(15, 200); @@ -310,14 +302,12 @@ void GUICharDefMenu::regenerateGui(v2u32 screensize) // hairtone //255 - //changeCtype(""); { core::rect rect(0, 0, 160, 20); rect += rightside + v2s32(45, 240); gui::IGUIStaticText *t = Environment->addStaticText(m_hairtone_types[m_parts["hairtone"]].c_str(), rect, false, true, this, -1); t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT); } - //changeCtype("C"); { core::rect rect(0, 0, 30, 30); rect += rightside + v2s32(15, 235); @@ -331,14 +321,12 @@ void GUICharDefMenu::regenerateGui(v2u32 screensize) // hair //290 - //changeCtype(""); { core::rect rect(0, 0, 160, 20); rect += rightside + v2s32(45, 275); gui::IGUIStaticText *t = Environment->addStaticText(m_hair_types[m_parts["hair"]].c_str(), rect, false, true, this, -1); t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT); } - //changeCtype("C"); { core::rect rect(0, 0, 30, 30); rect += rightside + v2s32(15, 270); @@ -352,14 +340,12 @@ void GUICharDefMenu::regenerateGui(v2u32 screensize) // eyes //325 - //changeCtype(""); { core::rect rect(0, 0, 160, 20); rect += rightside + v2s32(45, 315); gui::IGUIStaticText *t = Environment->addStaticText(m_eyes_types[m_parts["eyes"]].c_str(), rect, false, true, this, -1); t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT); } - //changeCtype("C"); { core::rect rect(0, 0, 30, 30); rect += rightside + v2s32(15, 305); @@ -373,14 +359,12 @@ void GUICharDefMenu::regenerateGui(v2u32 screensize) // t-shirt //370 - //changeCtype(""); { core::rect rect(0, 0, 160, 20); rect += rightside + v2s32(45, 355); gui::IGUIStaticText *t = Environment->addStaticText(m_shirt_types[m_parts["shirt"]].c_str(), rect, false, true, this, -1); t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT); } - //changeCtype("C"); { core::rect rect(0, 0, 30, 30); rect += rightside + v2s32(15, 350); @@ -394,14 +378,12 @@ void GUICharDefMenu::regenerateGui(v2u32 screensize) // pants //405 - //changeCtype(""); { core::rect rect(0, 0, 160, 20); rect += rightside + v2s32(45, 390); gui::IGUIStaticText *t = Environment->addStaticText(m_pants_types[m_parts["pants"]].c_str(), rect, false, true, this, -1); t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT); } - //changeCtype("C"); { core::rect rect(0, 0, 30, 30); rect += rightside + v2s32(15, 385); @@ -415,14 +397,12 @@ void GUICharDefMenu::regenerateGui(v2u32 screensize) // shoes //440 - //changeCtype(""); { core::rect rect(0, 0, 160, 20); rect += rightside + v2s32(45, 425); gui::IGUIStaticText *t = Environment->addStaticText(m_shoes_types[m_parts["shoes"]].c_str(), rect, false, true, this, -1); t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT); } - //changeCtype("C"); { core::rect rect(0, 0, 30, 30); rect += rightside + v2s32(15, 420); @@ -445,7 +425,6 @@ void GUICharDefMenu::regenerateGui(v2u32 screensize) rect += rightside + v2s32(130, 460); Environment->addButton(rect, this, GUI_ID_CD_QUIT_BUTTON, wgettext("Cancel")); } - changeCtype("C"); } void GUICharDefMenu::drawMenu() diff --git a/src/game.cpp b/src/game.cpp index 8893285..62b4388 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -352,9 +352,7 @@ void draw_hotbar(video::IVideoDriver *driver, gui::IGUIFont *font, p, sdim ); - changeCtype(""); font->draw(selected.c_str(), rect2, video::SColor(255,255,255,255), false, false, NULL); - changeCtype("C"); } } @@ -731,7 +729,6 @@ void drawLoadingScreen(video::IVideoDriver* driver, const std::wstring msg) } if (guienv) { std::wstring m; - changeCtype(""); if (msg != L"") { m = msg; }else{ @@ -742,7 +739,6 @@ void drawLoadingScreen(video::IVideoDriver* driver, const std::wstring msg) gui::IGUIStaticText *guitext = guienv->addStaticText(m.c_str(),rect); guienv->drawAll(); guitext->remove(); - changeCtype("C"); } driver->endScene(); @@ -810,9 +806,7 @@ void the_game( Draw "Loading" screen */ //draw_load_screen(L"Loading...", driver, font); - changeCtype(""); drawLoadingScreen(driver,wgettext("Loading...")); - changeCtype("C"); /* Create server. @@ -821,9 +815,7 @@ void the_game( SharedPtr server; if(address == ""){ //draw_load_screen(L"Creating server...", driver, font); - changeCtype(""); drawLoadingScreen(driver,wgettext("Creating server...")); - changeCtype("C"); infostream<<"Creating server"<start(port); @@ -834,16 +826,12 @@ void the_game( */ //draw_load_screen(L"Creating client...", driver, font); - changeCtype(""); drawLoadingScreen(driver,wgettext("Creating client...")); - changeCtype("C"); infostream<<"Creating client"< rect(0, 0, 400, 50); rect = rect + v2s32(size.X/2-400/2, size.Y/2-50/2-25); - Environment->addStaticText(wgettext("You died."), rect, false, - true, this, 256); + Environment->addStaticText(wgettext("You died."), rect, false, true, this, 256); } { core::rect rect(0, 0, 140, 30); rect = rect + v2s32(size.X/2-140/2, size.Y/2-30/2+25); - gui::IGUIElement *e = - Environment->addButton(rect, this, 257, - wgettext("Respawn")); + gui::IGUIElement *e = Environment->addButton(rect, this, 257, wgettext("Respawn")); Environment->setFocus(e); } - changeCtype("C"); } void GUIDeathScreen::drawMenu() diff --git a/src/guiFormSpecMenu.cpp b/src/guiFormSpecMenu.cpp index 70d0d87..386978e 100644 --- a/src/guiFormSpecMenu.cpp +++ b/src/guiFormSpecMenu.cpp @@ -39,8 +39,10 @@ #include "tile.h" // ITextureSource #include "path.h" #include "gui_colours.h" - #include "gettext.h" +#if USE_FREETYPE +#include "intlGUIEditBox.h" +#endif void drawInventoryItem(video::IVideoDriver *driver, gui::IGUIFont *font, @@ -316,7 +318,12 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize) // three cases: field and no label, label and no field, label and field if (flabel == "") { spec.send = true; - gui::IGUIEditBox *e = Environment->addEditBox(spec.fdefault.c_str(), rect, false, this, spec.fid); + gui::IGUIEditBox *e; +#if USE_FREETYPE + e = (gui::IGUIEditBox *) new gui::intlGUIEditBox(spec.fdefault.c_str(), true, Environment, this, spec.fid, rect); +#else + e = Environment->addEditBox(spec.fdefault.c_str(), rect, false, this, spec.fid); +#endif if (multi) { e->setMultiLine(true); e->setTextAlignment(gui::EGUIA_UPPERLEFT, gui::EGUIA_UPPERLEFT); @@ -333,7 +340,12 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize) Environment->addStaticText(spec.flabel.c_str(), rect, false, true, this, spec.fid); }else{ spec.send = true; - gui::IGUIEditBox *e = Environment->addEditBox(spec.fdefault.c_str(), rect, false, this, spec.fid); + gui::IGUIEditBox *e; +#if USE_FREETYPE + e = (gui::IGUIEditBox *) new gui::intlGUIEditBox(spec.fdefault.c_str(), true, Environment, this, spec.fid, rect); +#else + e = Environment->addEditBox(spec.fdefault.c_str(), rect, false, this, spec.fid); +#endif if (multi) { e->setMultiLine(true); e->setWordWrap(true); @@ -452,13 +464,11 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize) // If there's inventory, put the usage string at the bottom if (m_inventorylists.size()) { - changeCtype(""); core::rect rect(0, 0, size.X-padding.X*2, helptext_h); rect = rect + v2s32(size.X/2 - rect.getWidth()/2, size.Y-rect.getHeight()-5); const wchar_t *text = wgettext("Left click: Move all items, Right click: Move single item"); Environment->addStaticText(text, rect, false, true, this, 256); - changeCtype("C"); } // If there's fields, add a Proceed button if (m_fields.size() && bp_set != 2) @@ -474,7 +484,6 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize) recalculateAbsolutePosition(false); basepos = getBasePos(); - changeCtype(""); { v2s32 pos = basepos; pos.Y = ((m_fields.size()+1)*50); @@ -483,7 +492,6 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize) rect = core::rect(size.X/2-70, pos.Y, (size.X/2-70)+140, pos.Y+25); Environment->addButton(rect, this, 257, wgettext("Write It")); } - changeCtype("C"); } // Add tooltip { diff --git a/src/guiKeyChangeMenu.cpp b/src/guiKeyChangeMenu.cpp index db9a225..3da6b22 100644 --- a/src/guiKeyChangeMenu.cpp +++ b/src/guiKeyChangeMenu.cpp @@ -84,7 +84,6 @@ void GUIKeyChangeMenu::regenerateGui(v2u32 screensize) recalculateAbsolutePosition(false); v2s32 topleft(0, 0); - changeCtype(""); { core::rect < s32 > rect(0, 0, 620, 20); rect += topleft + v2s32(0, 10); @@ -313,7 +312,6 @@ void GUIKeyChangeMenu::regenerateGui(v2u32 screensize) Environment->addButton(rect, this, GUI_ID_ABORT_BUTTON, wgettext("Cancel")); } - changeCtype("C"); } void GUIKeyChangeMenu::drawMenu() @@ -436,7 +434,6 @@ bool GUIKeyChangeMenu::OnEvent(const SEvent& event) if (event.EventType == EET_KEY_INPUT_EVENT && activeKey >= 0 && event.KeyInput.PressedDown) { - changeCtype(""); KeyPress kp(event.KeyInput); if (activeKey == GUI_ID_KEY_FORWARD_BUTTON) @@ -509,7 +506,6 @@ bool GUIKeyChangeMenu::OnEvent(const SEvent& event) this->dump->setText(wgettext(kp.name())); this->key_dump = kp; } - changeCtype("C"); activeKey = -1; return true; } @@ -528,11 +524,6 @@ bool GUIKeyChangeMenu::OnEvent(const SEvent& event) } if (event.GUIEvent.EventType == gui::EGET_BUTTON_CLICKED) { - if(event.GUIEvent.Caller->getID() != GUI_ID_BACK_BUTTON && - event.GUIEvent.Caller->getID() != GUI_ID_ABORT_BUTTON) - { - changeCtype(""); - } switch (event.GUIEvent.Caller->getID()) { @@ -614,8 +605,6 @@ bool GUIKeyChangeMenu::OnEvent(const SEvent& event) this->range->setText(wgettext("press Key")); break; } - //Buttons - changeCtype("C"); } } diff --git a/src/guiMainMenu.cpp b/src/guiMainMenu.cpp index c652cf2..45e1121 100644 --- a/src/guiMainMenu.cpp +++ b/src/guiMainMenu.cpp @@ -38,6 +38,9 @@ #include #include "path.h" #include "gui_colours.h" +#if USE_FREETYPE +#include "intlGUIEditBox.h" +#endif #include "gettext.h" @@ -390,7 +393,6 @@ void GUIMainMenu::regenerateGui(v2u32 screensize) DesiredRect = rect; recalculateAbsolutePosition(false); - changeCtype(""); // Character Creator button { core::rect rect(0, 0, 200, 40); @@ -427,7 +429,6 @@ void GUIMainMenu::regenerateGui(v2u32 screensize) rect += v2s32(35, 440); Environment->addButton(rect, this, GUI_ID_TAB_QUIT, wgettext("Quit")); } - changeCtype("C"); v2s32 topleft_content(250, 0); v2s32 size_content = size - v2s32(300, 0); @@ -457,7 +458,6 @@ void GUIMainMenu::regenerateGui(v2u32 screensize) } if (m_data->selected_tab == TAB_MULTIPLAYER) { - changeCtype(""); { core::rect rect(0, 0, 550, 20); rect += topleft_content + v2s32(0, 20); @@ -471,47 +471,60 @@ void GUIMainMenu::regenerateGui(v2u32 screensize) rect += topleft_content + v2s32(120, 60); Environment->addStaticText(wgettext("Name/Password"), rect, false, true, this, -1); } - changeCtype("C"); { core::rect rect(0, 0, 230, 30); rect += topleft_content + v2s32(135, 90); - gui::IGUIElement *e = - Environment->addEditBox(text_name.c_str(), rect, false, this, GUI_ID_NAME_INPUT); + gui::IGUIEditBox *e; +#if USE_FREETYPE + e = (gui::IGUIEditBox *) new gui::intlGUIEditBox(text_name.c_str(), true, Environment, this, GUI_ID_NAME_INPUT, rect); +#else + e = Environment->addEditBox(text_name.c_str(), rect, false, this, GUI_ID_NAME_INPUT); +#endif if (text_name == L"") Environment->setFocus(e); } { core::rect rect(0, 0, 230, 30); rect += topleft_content + v2s32(135, 125); - gui::IGUIEditBox *e = - Environment->addEditBox(L"", rect, false, this, 264); + gui::IGUIEditBox *e; +#if USE_FREETYPE + e = (gui::IGUIEditBox *) new gui::intlGUIEditBox(L"", true, Environment, this, GUI_ID_PW_INPUT, rect); +#else + *e = Environment->addEditBox(L"", rect, false, this, GUI_ID_PW_INPUT); +#endif e->setPasswordBox(true); if (text_name != L"" && text_address != L"") Environment->setFocus(e); } - changeCtype(""); // Address + port { core::rect rect(0, 0, 110, 20); rect += topleft_content + v2s32(120, 170); Environment->addStaticText(wgettext("Address/Port"), rect, false, true, this, -1); } - changeCtype("C"); { core::rect rect(0, 0, 230, 30); rect += topleft_content + v2s32(135, 200); - gui::IGUIElement *e = - Environment->addEditBox(text_address.c_str(), rect, false, this, GUI_ID_ADDRESS_INPUT); + gui::IGUIEditBox *e; +#if USE_FREETYPE + e = (gui::IGUIEditBox *) new gui::intlGUIEditBox(text_address.c_str(), true, Environment, this, GUI_ID_ADDRESS_INPUT, rect); +#else + e = Environment->addEditBox(text_address.c_str(), rect, false, this, GUI_ID_ADDRESS_INPUT); +#endif if (text_name != L"" && text_address == L"") Environment->setFocus(e); } { core::rect rect(0, 0, 120, 30); rect += topleft_content + v2s32(245, 240); - Environment->addEditBox(text_port.c_str(), rect, false, this, GUI_ID_PORT_INPUT); + gui::IGUIEditBox *e; +#if USE_FREETYPE + e = (gui::IGUIEditBox *) new gui::intlGUIEditBox(text_port.c_str(), true, Environment, this, GUI_ID_PORT_INPUT, rect); +#else + e = Environment->addEditBox(text_port.c_str(), rect, false, this, GUI_ID_PORT_INPUT); +#endif } - changeCtype(""); // Start game button { core::rect rect(0, 0, 180, 30); @@ -519,7 +532,6 @@ void GUIMainMenu::regenerateGui(v2u32 screensize) Environment->addButton(rect, this, GUI_ID_JOIN_GAME_BUTTON, wgettext("Connect")); } }else if (m_data->selected_tab == TAB_SETTINGS) { - changeCtype(""); { core::rect rect(0, 0, 550, 20); rect += topleft_content + v2s32(0, 20); @@ -584,7 +596,6 @@ void GUIMainMenu::regenerateGui(v2u32 screensize) Environment->addButton(rect, this, GUI_ID_CHANGE_KEYS_BUTTON, wgettext("Change keys")); } }else if (m_data->selected_tab == TAB_SINGLEPLAYER) { - changeCtype(""); { core::rect rect(0, 0, 550, 20); rect += topleft_content + v2s32(0, 20); @@ -627,7 +638,6 @@ void GUIMainMenu::regenerateGui(v2u32 screensize) Environment->addButton(rect, this, GUI_ID_JOIN_GAME_BUTTON, wgettext("Start Game")); } }else if (m_data->selected_tab == TAB_SINGLEPLAYER_ADVANCED) { - changeCtype(""); { core::rect rect(0, 0, 550, 20); rect += topleft_content + v2s32(0, 20); @@ -726,7 +736,6 @@ void GUIMainMenu::regenerateGui(v2u32 screensize) Environment->addButton(rect, this, GUI_ID_JOIN_GAME_BUTTON, wgettext("Start Game")); } }else if (m_data->selected_tab == TAB_SINGLEPLAYER_MAP) { - changeCtype(""); { core::rect rect(0, 0, 550, 20); rect += topleft_content + v2s32(0, 20); @@ -822,13 +831,16 @@ void GUIMainMenu::regenerateGui(v2u32 screensize) gui::IGUIStaticText *t = Environment->addStaticText(wgettext("Map Seed"), rect, false, true, this, -1); t->setTextAlignment(gui::EGUIA_LOWERRIGHT, gui::EGUIA_UPPERLEFT); } - changeCtype("C"); { core::rect rect(0, 0, 190, 30); rect += topleft_content + v2s32(190, 260); - Environment->addEditBox(fixed_seed.c_str(), rect, false, this, GUI_ID_MAP_SEED_INPUT); + gui::IGUIEditBox *e; +#if USE_FREETYPE + e = (gui::IGUIEditBox *) new gui::intlGUIEditBox(fixed_seed.c_str(), true, Environment, this, GUI_ID_MAP_SEED_INPUT, rect); +#else + e = Environment->addEditBox(fixed_seed.c_str(), rect, false, this, GUI_ID_MAP_SEED_INPUT); +#endif } - changeCtype(""); } }else{ { @@ -882,7 +894,6 @@ void GUIMainMenu::regenerateGui(v2u32 screensize) t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT); } } - changeCtype("C"); } void GUIMainMenu::drawMenu() @@ -936,7 +947,7 @@ void GUIMainMenu::acceptInput() } } { - gui::IGUIElement *e = getElementFromId(264); + gui::IGUIElement *e = getElementFromId(GUI_ID_PW_INPUT); if(e != NULL) m_data->password = e->getText(); } @@ -1363,7 +1374,7 @@ bool GUIMainMenu::OnEvent(const SEvent& event) case GUI_ID_ADDRESS_INPUT: case GUI_ID_PORT_INPUT: case GUI_ID_NAME_INPUT: - case 264: + case GUI_ID_PW_INPUT: acceptInput(); quitMenu(); return true; diff --git a/src/guiMainMenu.h b/src/guiMainMenu.h index f7e3c70..8773492 100644 --- a/src/guiMainMenu.h +++ b/src/guiMainMenu.h @@ -36,6 +36,7 @@ enum { GUI_ID_QUIT_BUTTON = 101, GUI_ID_NAME_INPUT, + GUI_ID_PW_INPUT, GUI_ID_ADDRESS_INPUT, GUI_ID_PORT_INPUT, GUI_ID_FANCYTREE_CB, diff --git a/src/guiMessageMenu.cpp b/src/guiMessageMenu.cpp index 3dca625..4125f08 100644 --- a/src/guiMessageMenu.cpp +++ b/src/guiMessageMenu.cpp @@ -104,7 +104,6 @@ void GUIMessageMenu::regenerateGui(v2u32 screensize) Environment->addStaticText(m_message_text.c_str(), rect, false, true, this, 256); } - changeCtype(""); { core::rect rect(0, 0, 140, 30); rect = rect + v2s32(size.X/2-140/2, size.Y/2-30/2+25); @@ -113,7 +112,6 @@ void GUIMessageMenu::regenerateGui(v2u32 screensize) wgettext("Continue")); Environment->setFocus(e); } - changeCtype("C"); } void GUIMessageMenu::drawMenu() diff --git a/src/guiPasswordChange.cpp b/src/guiPasswordChange.cpp index 63ae050..b4f087b 100644 --- a/src/guiPasswordChange.cpp +++ b/src/guiPasswordChange.cpp @@ -33,9 +33,11 @@ #include #include #include - #include "gettext.h" #include "gui_colours.h" +#if USE_FREETYPE +#include "intlGUIEditBox.h" +#endif const int ID_oldPassword = 256; const int ID_newPassword1 = 257; @@ -98,57 +100,59 @@ void GUIPasswordChange::regenerateGui(v2u32 screensize) Add stuff */ s32 ypos = 30; - changeCtype(""); { core::rect rect(0, 0, 110, 20); rect += topleft_client + v2s32(35, ypos+6); - Environment->addStaticText(wgettext("Old Password"), - rect, false, true, this, -1); + Environment->addStaticText(wgettext("Old Password"), rect, false, true, this, -1); } - changeCtype("C"); { core::rect rect(0, 0, 230, 30); rect += topleft_client + v2s32(160, ypos); - gui::IGUIEditBox *e = - Environment->addEditBox(L"", rect, false, this, ID_oldPassword); + gui::IGUIEditBox *e; +#if USE_FREETYPE + e = (gui::IGUIEditBox *) new gui::intlGUIEditBox(L"", true, Environment, this, ID_oldPassword, rect); +#else + e = Environment->addEditBox(L"", rect, false, this, ID_oldPassword); +#endif Environment->setFocus(e); e->setPasswordBox(true); } ypos += 50; - changeCtype(""); { core::rect rect(0, 0, 110, 20); rect += topleft_client + v2s32(35, ypos+6); - Environment->addStaticText(wgettext("New Password"), - rect, false, true, this, -1); + Environment->addStaticText(wgettext("New Password"), rect, false, true, this, -1); } - changeCtype("C"); { core::rect rect(0, 0, 230, 30); rect += topleft_client + v2s32(160, ypos); - gui::IGUIEditBox *e = - Environment->addEditBox(L"", rect, false, this, ID_newPassword1); + gui::IGUIEditBox *e; +#if USE_FREETYPE + e = (gui::IGUIEditBox *) new gui::intlGUIEditBox(L"", true, Environment, this, ID_newPassword1, rect); +#else + e = Environment->addEditBox(L"", rect, false, this, ID_newPassword1); +#endif e->setPasswordBox(true); } ypos += 50; - changeCtype(""); { core::rect rect(0, 0, 110, 20); rect += topleft_client + v2s32(35, ypos+6); - Environment->addStaticText(wgettext("Confirm Password"), - rect, false, true, this, -1); + Environment->addStaticText(wgettext("Confirm Password"), rect, false, true, this, -1); } - changeCtype("C"); { core::rect rect(0, 0, 230, 30); rect += topleft_client + v2s32(160, ypos); - gui::IGUIEditBox *e = - Environment->addEditBox(L"", rect, false, this, ID_newPassword2); + gui::IGUIEditBox *e; +#if USE_FREETYPE + e = (gui::IGUIEditBox *) new gui::intlGUIEditBox(L"", true, Environment, this, ID_newPassword2, rect); +#else + e = Environment->addEditBox(L"", rect, false, this, ID_newPassword2); +#endif e->setPasswordBox(true); } ypos += 50; - changeCtype(""); { core::rect rect(0, 0, 140, 30); rect = rect + v2s32(size.X/2-140/2, ypos); @@ -160,12 +164,9 @@ void GUIPasswordChange::regenerateGui(v2u32 screensize) core::rect rect(0, 0, 300, 20); rect += topleft_client + v2s32(35, ypos); IGUIElement *e = - Environment->addStaticText( - wgettext("Passwords do not match!"), - rect, false, true, this, ID_message); + Environment->addStaticText(wgettext("Passwords do not match!"), rect, false, true, this, ID_message); e->setVisible(false); } - changeCtype("C"); } diff --git a/src/guiPauseMenu.cpp b/src/guiPauseMenu.cpp index db2b854..95a1d79 100644 --- a/src/guiPauseMenu.cpp +++ b/src/guiPauseMenu.cpp @@ -85,10 +85,9 @@ void GUIPauseMenu::regenerateGui(v2u32 screensize) recalculateAbsolutePosition(false); v2s32 size = rect.getSize(); - changeCtype(""); { - core::rect rect(0, 0, 380, 20); - rect = rect + v2s32(20 , 10); + core::rect rect(0, 0, 340, 20); + rect = rect + v2s32(0 , 10); v2u32 max_texture_size; { @@ -99,8 +98,8 @@ void GUIPauseMenu::regenerateGui(v2u32 screensize) Environment->addStaticText(wgettext("Voxelands by darkrose and contributors"), rect, false, true, this, 259); } { - core::rect rect(0, 0, 200, 20); - rect = rect + v2s32(85 , 30); + core::rect rect(0, 0, 340, 20); + rect = rect + v2s32(0 , 30); v2u32 max_texture_size; { @@ -111,8 +110,8 @@ void GUIPauseMenu::regenerateGui(v2u32 screensize) Environment->addStaticText(L"www.voxelands.com", rect, false, true, this, 259); } { - core::rect rect(0, 0, 205, 20); - rect = rect + v2s32(70,50); + core::rect rect(0, 0, 340, 20); + rect = rect + v2s32(0,50); v2u32 max_texture_size; { @@ -131,47 +130,28 @@ void GUIPauseMenu::regenerateGui(v2u32 screensize) const s32 btn_num = 4; s32 btn_y = (size.Y/2-((btn_num*btn_height+(btn_num-1)*btn_gap))/2)+40; { - core::rect rect(0, 0, 140, btn_height); - rect = rect + v2s32(size.X/2-140/2, btn_y); + core::rect rect(0, 0, 180, btn_height); + rect = rect + v2s32(size.X/2-180/2, btn_y); Environment->addButton(rect, this, 256, wgettext("Continue")); } btn_y += btn_height + btn_gap; { - core::rect rect(0, 0, 140, btn_height); - rect = rect + v2s32(size.X/2-140/2, btn_y); + core::rect rect(0, 0, 180, btn_height); + rect = rect + v2s32(size.X/2-180/2, btn_y); Environment->addButton(rect, this, 261, wgettext("Change Password")); } btn_y += btn_height + btn_gap; { - core::rect rect(0, 0, 140, btn_height); - rect = rect + v2s32(size.X/2-140/2, btn_y); + core::rect rect(0, 0, 180, btn_height); + rect = rect + v2s32(size.X/2-180/2, btn_y); Environment->addButton(rect, this, 260, wgettext("Disconnect")); } btn_y += btn_height + btn_gap; { - core::rect rect(0, 0, 140, btn_height); - rect = rect + v2s32(size.X/2-140/2, btn_y); + core::rect rect(0, 0, 180, btn_height); + rect = rect + v2s32(size.X/2-180/2, btn_y); Environment->addButton(rect, this, 257, wgettext("Exit to OS")); } - - //{ - //core::rect rect(0, 0, 180, 240); - //rect = rect + v2s32(size.X/2 + 90, size.Y/2-rect.getHeight()/2); - //Environment->addStaticText(chartowchar_t(gettext( - //"Default Controls:\n" - //"- WASD: Walk\n" - //"- Mouse left: dig/hit\n" - //"- Mouse right: place/use\n" - //"- Mouse wheel: select item\n" - //"- 0...9: select item\n" - //"- Shift: sneak\n" - //"- R: Toggle viewing all loaded chunks\n" - //"- I: Inventory menu\n" - //"- ESC: This menu\n" - //"- T: Chat\n" - //)), rect, false, true, this, 258); - //} - changeCtype("C"); } void GUIPauseMenu::drawMenu() diff --git a/src/guiTextInputMenu.cpp b/src/guiTextInputMenu.cpp index 08e10de..dec7d50 100644 --- a/src/guiTextInputMenu.cpp +++ b/src/guiTextInputMenu.cpp @@ -32,9 +32,11 @@ #include #include #include - #include "gettext.h" #include "gui_colours.h" +#if USE_FREETYPE +#include "intlGUIEditBox.h" +#endif GUITextInputMenu::GUITextInputMenu(gui::IGUIEnvironment* env, gui::IGUIElement* parent, s32 id, @@ -111,10 +113,13 @@ void GUITextInputMenu::regenerateGui(v2u32 screensize) Add stuff */ { - //core::rect rect(0, 0, 300, 30); - //rect = rect + v2s32(size.X/2-300/2, size.Y/2-30/2-25); core::rect rect(5, 0, 290, 30); - gui::IGUIElement *e = Environment->addEditBox(text.c_str(), rect, false, this, 256); + gui::IGUIEditBox *e; +#if USE_FREETYPE + e = (gui::IGUIEditBox *) new gui::intlGUIEditBox(text.c_str(), true, Environment, this, 256, rect); +#else + e = Environment->addEditBox(text.c_str(), rect, false, this, 256); +#endif Environment->setFocus(e); @@ -124,14 +129,6 @@ void GUITextInputMenu::regenerateGui(v2u32 screensize) evt.KeyInput.PressedDown = true; e->OnEvent(evt); } - //changeCtype(""); - //{ - //core::rect rect(0, 0, 140, 30); - //rect = rect + v2s32(size.X/2-140/2, size.Y/2-30/2+25); - //Environment->addButton(rect, this, 257, - //wgettext("Write It")); - //} - //changeCtype("C"); } void GUITextInputMenu::drawMenu() diff --git a/src/intlGUIEditBox.cpp b/src/intlGUIEditBox.cpp new file mode 100644 index 0000000..671d16c --- /dev/null +++ b/src/intlGUIEditBox.cpp @@ -0,0 +1,1538 @@ +// 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" +#include "log.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& 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 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) || defined(__linux) || defined(__FreeBSD__)) + // ################################################################ + // 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: + // Handle numpad input + if (event.KeyInput.Char != 0) { + inputChar(event.KeyInput.Char); + return true; + } + { + 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: + // Handle numpad input + if (event.KeyInput.Char != 0) { + inputChar(event.KeyInput.Char); + return true; + } + { + + 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: + // Handle numpad input + if (event.KeyInput.Char != 0) { + inputChar(event.KeyInput.Char); + return true; + } + 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: + // Handle numpad input + if (event.KeyInput.Char != 0) { + inputChar(event.KeyInput.Char); + return true; + } + 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: + // Handle numpad input + if (event.KeyInput.Char != 0) { + inputChar(event.KeyInput.Char); + return true; + } + 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: + // Handle numpad input + if (event.KeyInput.Char != 0) { + inputChar(event.KeyInput.Char); + return true; + } + 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; + // Handle numpad input + if (event.KeyInput.Char != 0) { + inputChar(event.KeyInput.Char); + return true; + } + 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; + + EGUI_DEFAULT_COLOR bgCol = EGDC_GRAY_EDITABLE; + if ( isEnabled() ) + bgCol = focus ? EGDC_FOCUSED_EDITABLE : EGDC_EDITABLE; + + // draw the background + + skin->draw2DRectangle(this, skin->getColor(bgCol), AbsoluteRect, &AbsoluteClippingRect); + + core::rect 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 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 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(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; igetDimension(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_ diff --git a/src/intlGUIEditBox.h b/src/intlGUIEditBox.h new file mode 100644 index 0000000..350c341 --- /dev/null +++ b/src/intlGUIEditBox.h @@ -0,0 +1,185 @@ +// 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 + +#ifndef __C_INTL_GUI_EDIT_BOX_H_INCLUDED__ +#define __C_INTL_GUI_EDIT_BOX_H_INCLUDED__ + +#include "IrrCompileConfig.h" +//#ifdef _IRR_COMPILE_WITH_GUI_ + +#include "IGUIEditBox.h" +#include "irrArray.h" +#include "IOSOperator.h" + +namespace irr +{ +namespace gui +{ + class intlGUIEditBox : public IGUIEditBox + { + public: + + //! constructor + intlGUIEditBox(const wchar_t* text, bool border, IGUIEnvironment* environment, + IGUIElement* parent, s32 id, const core::rect& rectangle); + + //! destructor + virtual ~intlGUIEditBox(); + + //! Sets another skin independent font. + virtual void setOverrideFont(IGUIFont* font=0); + + //! Gets the override font (if any) + /** \return The override font (may be 0) */ + virtual IGUIFont* getOverrideFont() const; + + //! Get the font which is used right now for drawing + /** Currently this is the override font when one is set and the + font of the active skin otherwise */ + virtual IGUIFont* getActiveFont() const; + + //! Sets another color for the text. + virtual void setOverrideColor(video::SColor color); + + //! Gets the override color + virtual video::SColor getOverrideColor() const; + + //! Sets if the text should use the overide color or the + //! color in the gui skin. + virtual void enableOverrideColor(bool enable); + + //! Checks if an override color is enabled + /** \return true if the override color is enabled, false otherwise */ + virtual bool isOverrideColorEnabled(void) const; + + //! Sets whether to draw the background + virtual void setDrawBackground(bool draw); + + //! Turns the border on or off + virtual void setDrawBorder(bool border); + + //! Enables or disables word wrap for using the edit box as multiline text editor. + virtual void setWordWrap(bool enable); + + //! Checks if word wrap is enabled + //! \return true if word wrap is enabled, false otherwise + virtual bool isWordWrapEnabled() const; + + //! Enables or disables newlines. + /** \param enable: If set to true, the EGET_EDITBOX_ENTER event will not be fired, + instead a newline character will be inserted. */ + virtual void setMultiLine(bool enable); + + //! Checks if multi line editing is enabled + //! \return true if mult-line is enabled, false otherwise + virtual bool isMultiLineEnabled() const; + + //! Enables or disables automatic scrolling with cursor position + //! \param enable: If set to true, the text will move around with the cursor position + virtual void setAutoScroll(bool enable); + + //! Checks to see if automatic scrolling is enabled + //! \return true if automatic scrolling is enabled, false if not + virtual bool isAutoScrollEnabled() const; + + //! Gets the size area of the text in the edit box + //! \return Returns the size in pixels of the text + virtual core::dimension2du getTextDimension(); + + //! Sets text justification + virtual void setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT vertical); + + //! called if an event happened. + virtual bool OnEvent(const SEvent& event); + + //! draws the element and its children + virtual void draw(); + + //! Sets the new caption of this element. + virtual void setText(const wchar_t* text); + + //! 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. + virtual void setMax(u32 max); + + //! Returns maximum amount of characters, previously set by setMax(); + virtual u32 getMax() const; + + //! Sets whether the edit box is a password box. Setting this to true will + /** disable MultiLine, WordWrap and the ability to copy with ctrl+c or ctrl+x + \param passwordBox: true to enable password, false to disable + \param passwordChar: the character that is displayed instead of letters */ + virtual void setPasswordBox(bool passwordBox, wchar_t passwordChar = L'*'); + + //! Returns true if the edit box is currently a password box. + virtual bool isPasswordBox() const; + + //! Updates the absolute position, splits text if required + virtual void updateAbsolutePosition(); + + //! Writes attributes of the element. + virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const; + + //! Reads attributes of the element + virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options); + + virtual bool isDrawBackgroundEnabled() const { return false; } + virtual bool isDrawBorderEnabled() const { return true; } + virtual void setCursorChar(const wchar_t cursorChar) { }; + virtual wchar_t getCursorChar() const { return L'_'; }; + virtual void setCursorBlinkTime(irr::u32 timeMs) { }; + virtual irr::u32 getCursorBlinkTime() const { return 500; } ; + + protected: + //! Breaks the single text line. + void breakText(); + //! sets the area of the given line + void setTextRect(s32 line); + //! returns the line number that the cursor is on + s32 getLineFromPos(s32 pos); + //! adds a letter to the edit box + void inputChar(wchar_t c); + //! calculates the current scroll position + void calculateScrollPos(); + //! send some gui event to parent + void sendGuiEvent(EGUI_EVENT_TYPE type); + //! set text markers + void setTextMarkers(s32 begin, s32 end); + + bool processKey(const SEvent& event); + bool processMouse(const SEvent& event); + s32 getCursorPos(s32 x, s32 y); + + bool MouseMarking; + bool Border; + bool OverrideColorEnabled; + s32 MarkBegin; + s32 MarkEnd; + + video::SColor OverrideColor; + gui::IGUIFont *OverrideFont, *LastBreakFont; + IOSOperator* Operator; + + u32 BlinkStartTime; + s32 CursorPos; + s32 HScrollPos, VScrollPos; // scroll position in characters + u32 Max; + + bool WordWrap, MultiLine, AutoScroll, PasswordBox; + wchar_t PasswordChar; + EGUI_ALIGNMENT HAlign, VAlign; + + core::array< core::stringw > BrokenText; + core::array< s32 > BrokenTextPositions; + + core::rect CurrentTextRect, FrameRect; // temporary values + }; + + +} // end namespace gui +} // end namespace irr + +//#endif // _IRR_COMPILE_WITH_GUI_ +#endif // __C_GUI_EDIT_BOX_H_INCLUDED__ diff --git a/src/main.cpp b/src/main.cpp index 9664e9f..babdc23 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1130,9 +1130,7 @@ int main(int argc, char *argv[]) // If font was not found, this will get us one font = skin->getFont(); assert(font); - changeCtype(""); drawLoadingScreen(driver,wgettext("Setting Up UI")); - changeCtype("C"); u32 text_height = font->getDimension(L"Hello, world!").Height; infostream<<"text_height="<