diff --git a/VisualStudio/fheroes2/sources.props b/VisualStudio/fheroes2/sources.props index 529b2ba4eed..901b031e4cd 100644 --- a/VisualStudio/fheroes2/sources.props +++ b/VisualStudio/fheroes2/sources.props @@ -3,6 +3,7 @@ + @@ -240,6 +241,7 @@ + diff --git a/src/engine/char_encoding.cpp b/src/engine/char_encoding.cpp new file mode 100644 index 00000000000..52b6f07cd71 --- /dev/null +++ b/src/engine/char_encoding.cpp @@ -0,0 +1,135 @@ +/*************************************************************************** + * fheroes2: https://github.com/ihhub/fheroes2 * + * Copyright (C) 2023 * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include "char_encoding.h" + +#include +#include + +namespace +{ + // All code page related array indexes are equal to index + 128 value in their code pages. + // For example, a first element in an array is actually value 128 in their code page. + const std::array cp1251CodePoints{ 0x0402, 0x0403, 0x201A, 0x0453, 0x201E, 0x2026, 0x2020, 0x2021, 0x20AC, 0x2030, 0x0409, 0x2039, 0x040A, + 0x040C, 0x040B, 0x040F, 0x0452, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x0000, 0x2122, + 0x0459, 0x203A, 0x045A, 0x045C, 0x045B, 0x045F, 0x00A0, 0x040E, 0x045E, 0x0408, 0x00A4, 0x0490, 0x00A6, + 0x00A7, 0x0401, 0x00A9, 0x0404, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x0407, 0x00B0, 0x00B1, 0x0406, 0x0456, + 0x0491, 0x00B5, 0x00B6, 0x00B7, 0x0451, 0x2116, 0x0454, 0x00BB, 0x0458, 0x0405, 0x0455, 0x0457, 0x0410, + 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, + 0x041E, 0x041F, 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042A, + 0x042B, 0x042C, 0x042D, 0x042E, 0x042F, 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, + 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F, 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, + 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F }; + + uint8_t codePointToCP1251( const uint32_t value ) + { + if ( value < 0x80 ) { + // This is an ASCII character that is a part of this code page. + return static_cast( value ); + } + + // TODO: optimize the code to avoid looping. + for ( size_t i = 0; i < cp1251CodePoints.size(); ++i ) { + if ( cp1251CodePoints[i] == value ) { + return static_cast( i + 128 ); + } + } + + // This is an invalid character. + return 0; + } +} + +namespace Encoding +{ + bool utf8ToCodePoint( const uint8_t * data, size_t length, uint32_t & codePoint ) + { + if ( data == nullptr || length == 0 ) { + // Why are you trying to decode empty data? + assert( 0 ); + return false; + } + + if ( length > 4 ) { + // Length cannot be longer than 4. + length = 4; + } + + if ( data[0] < 0x80 ) { + // This is an ASCII character. No need further processing. + codePoint = data[0]; + return true; + } + + if ( length < 2 || ( data[1] >> 6 ) != 2 ) { + // This is an invalid character. + return false; + } + + if ( ( data[0] >> 5 ) == 6 ) { + // This is a 2 byte character. + codePoint = ( data[1] & 0x3F ) | ( data[0] & 0x1F ) << 6; + return true; + } + + if ( length < 3 || ( data[2] >> 6 ) != 2 ) { + // This is an invalid character. + return false; + } + + if ( ( data[0] >> 4 ) == 14 ) { + // This is a 3 byte character. + codePoint = ( data[2] & 0x3F ) | ( ( data[1] & 0x3F ) << 6 ) | ( data[0] & 0x0F ) << 12; + return true; + } + + if ( length != 4 || ( data[3] >> 6 ) != 2 ) { + // This is an invalid character. + return false; + } + + if ( ( data[0] >> 3 ) != 30 ) { + // This is an invalid character. + return false; + } + + // This is a 4 byte character. + codePoint = ( data[3] & 0x3F ) | ( ( data[2] & 0x3F ) << 6 ) | ( ( data[1] & 0x3F ) << 12 ) | ( data[0] & 0x07 ) << 18; + return true; + } + + uint8_t getCodePageCharacter( const uint32_t value, const CodePage codePage ) + { + if ( codePage == CodePage::CP1251 ) { + return codePointToCP1251( value ); + } + + if ( value < 0x80 ) { + return static_cast( value ); + } + + return 0; + } + + bool isASCIICharacter( const uint32_t value ) + { + return ( value < 0x80 ); + } +} diff --git a/src/engine/char_encoding.h b/src/engine/char_encoding.h new file mode 100644 index 00000000000..617d62b311a --- /dev/null +++ b/src/engine/char_encoding.h @@ -0,0 +1,44 @@ +/*************************************************************************** + * fheroes2: https://github.com/ihhub/fheroes2 * + * Copyright (C) 2023 * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#pragma once + +#include +#include + +namespace Encoding +{ + enum class CodePage : uint8_t + { + ASCII, + CP1250, + CP1251, + CP1252, + CP1254, + CP1258, + ISO8859_16 + }; + + bool utf8ToCodePoint( const uint8_t * data, size_t length, uint32_t & codePoint ); + + uint8_t getCodePageCharacter( const uint32_t value, const CodePage codePage ); + + bool isASCIICharacter( const uint32_t value ); +} diff --git a/src/engine/localevent.cpp b/src/engine/localevent.cpp index 17c3d5ca43e..6068ba6c0b6 100644 --- a/src/engine/localevent.cpp +++ b/src/engine/localevent.cpp @@ -43,6 +43,7 @@ #include #include "audio.h" +#include "char_encoding.h" #include "image.h" #include "render_processor.h" #include "screen.h" @@ -613,53 +614,6 @@ namespace fheroes2 return false; } - - size_t InsertKeySym( std::string & res, size_t pos, const Key key, const int32_t mod ) - { - switch ( key ) { - case fheroes2::Key::KEY_BACKSPACE: - if ( !res.empty() && pos ) { - if ( pos >= res.size() ) - res.resize( res.size() - 1 ); - else - res.erase( pos - 1, 1 ); - --pos; - } - break; - case fheroes2::Key::KEY_DELETE: - if ( !res.empty() ) { - if ( pos < res.size() ) - res.erase( pos, 1 ); - } - break; - - case fheroes2::Key::KEY_LEFT: - if ( pos ) - --pos; - break; - case fheroes2::Key::KEY_RIGHT: - if ( pos < res.size() ) - ++pos; - break; - case fheroes2::Key::KEY_HOME: - pos = 0; - break; - case fheroes2::Key::KEY_END: - pos = res.size(); - break; - - default: { - char c = getCharacterFromPressedKey( key, mod ); - - if ( c ) { - res.insert( pos, 1, c ); - ++pos; - } - } - } - - return pos; - } } LocalEvent::LocalEvent() @@ -723,6 +677,19 @@ LocalEvent & LocalEvent::GetClean() return le; } +void LocalEvent::enableTextInput() +{ + SDL_StartTextInput(); +} + +void LocalEvent::disableTextInput() +{ + // If this assertion blows up then you are trying to disable text input twice! + assert( SDL_IsTextInputActive() ); + + SDL_StopTextInput(); +} + bool LocalEvent::HandleEvents( const bool sleepAfterEventProcessing, const bool allowExit /* = false */ ) { // Event processing might be computationally heavy. @@ -772,6 +739,7 @@ bool LocalEvent::HandleEvents( const bool sleepAfterEventProcessing, const bool break; case SDL_KEYDOWN: case SDL_KEYUP: + _lastPressedCodePoint = 0; HandleKeyboardEvent( event.key ); break; case SDL_MOUSEMOTION: @@ -833,9 +801,14 @@ bool LocalEvent::HandleEvents( const bool sleepAfterEventProcessing, const bool HandleRenderDeviceResetEvent(); renderRoi = { 0, 0, display.width(), display.height() }; break; - case SDL_TEXTINPUT: - // Keyboard events on Android should be processed here. Use event.text.text to extract text input. + case SDL_TEXTINPUT: { + _lastPressedCodePoint = event.key.keysym.sym; + if ( !Encoding::utf8ToCodePoint( reinterpret_cast( event.text.text ), 32, _lastPressedCodePoint ) ) { + // Not a valid UTF-8 character. Maybe it is an unsupported OS. + _lastPressedCodePoint = 0; + } break; + } case SDL_TEXTEDITING: // An event when a user pressed a button on a keyboard. Not all buttons are supported. This event should be used mainly on Android devices. break; @@ -1259,25 +1232,25 @@ bool LocalEvent::MousePressRight() const void LocalEvent::HandleKeyboardEvent( const SDL_KeyboardEvent & event ) { - const fheroes2::Key key = getKeyFromSDL( event.keysym.sym ); - if ( key == fheroes2::Key::NONE ) { - return; - } - if ( event.type == SDL_KEYDOWN ) { SetModes( KEY_PRESSED ); SetModes( KEY_HOLD ); - if ( _globalKeyDownEventHook ) { + const fheroes2::Key key = getKeyFromSDL( event.keysym.sym ); + if ( key != fheroes2::Key::NONE && _globalKeyDownEventHook ) { + key_value = key; _globalKeyDownEventHook( key, getKeyModifierFromSDL( event.keysym.mod ) ); } + else { + key_value = fheroes2::Key::NONE; + } } else if ( event.type == SDL_KEYUP ) { ResetModes( KEY_PRESSED ); ResetModes( KEY_HOLD ); - } - key_value = key; + key_value = fheroes2::Key::NONE; + } } void LocalEvent::HandleMouseMotionEvent( const SDL_MouseMotionEvent & motion ) @@ -1580,3 +1553,61 @@ void LocalEvent::setEventProcessingStates() // We do not support custom user events as of now. setEventProcessingState( SDL_USEREVENT, false ); } + +size_t LocalEvent::insertLastPressedSymbol( std::string & res, size_t pos, const Encoding::CodePage codePage ) const +{ + switch ( key_value ) { + case fheroes2::Key::KEY_BACKSPACE: + if ( !res.empty() && pos > 0 ) { + if ( pos >= res.size() ) { + res.resize( res.size() - 1 ); + } + else { + res.erase( pos - 1, 1 ); + } + + --pos; + } + return pos; + case fheroes2::Key::KEY_DELETE: + if ( !res.empty() ) { + if ( pos < res.size() ) { + res.erase( pos, 1 ); + } + } + return pos; + case fheroes2::Key::KEY_LEFT: + if ( pos > 0 ) { + --pos; + } + return pos; + case fheroes2::Key::KEY_RIGHT: + if ( pos < res.size() ) { + ++pos; + } + return pos; + case fheroes2::Key::KEY_HOME: + return 0; + case fheroes2::Key::KEY_END: + return res.size(); + default: + break; + } + + if ( Encoding::isASCIICharacter( _lastPressedCodePoint ) ) { + const char character = getCharacterFromPressedKey( key_value, LocalEvent::getCurrentKeyModifiers() ); + if ( character != 0 ) { + res.insert( pos, 1, character ); + ++pos; + } + } + else { + const uint8_t character = Encoding::getCodePageCharacter( _lastPressedCodePoint, codePage ); + if ( character != 0 ) { + res.insert( pos, 1, static_cast( character ) ); + ++pos; + } + } + + return pos; +} diff --git a/src/engine/localevent.h b/src/engine/localevent.h index 0512450af68..e8202a5ad74 100644 --- a/src/engine/localevent.h +++ b/src/engine/localevent.h @@ -38,6 +38,11 @@ #include "math_base.h" #include "timing.h" +namespace Encoding +{ + enum class CodePage : uint8_t; +} + namespace fheroes2 { enum class Key : int32_t @@ -174,8 +179,6 @@ namespace fheroes2 const char * KeySymGetName( const Key key ); bool PressIntKey( uint32_t max, uint32_t & result ); - - size_t InsertKeySym( std::string & res, size_t pos, const Key key, const int32_t mod ); } class LocalEvent @@ -184,6 +187,16 @@ class LocalEvent static LocalEvent & Get(); static LocalEvent & GetClean(); // reset all previous event statuses and return a reference for events + static int32_t getCurrentKeyModifiers(); + + static void OpenTouchpad(); + + static void setEventProcessingStates(); + + static void enableTextInput(); + + static void disableTextInput(); + void setGlobalMouseMotionEventHook( std::function hook ) { _globalMouseMotionEventHook = std::move( hook ); @@ -194,8 +207,6 @@ class LocalEvent _globalKeyDownEventHook = std::move( hook ); } - static void setEventProcessingStates(); - bool HandleEvents( const bool sleepAfterEventProcessing = true, const bool allowExit = false ); bool MouseMotion() const @@ -292,13 +303,9 @@ class LocalEvent return key_value; } - static int32_t getCurrentKeyModifiers(); - void OpenController(); void CloseController(); - static void OpenTouchpad(); - void SetControllerPointerSpeed( const int newSpeed ) { if ( newSpeed > 0 ) { @@ -306,6 +313,8 @@ class LocalEvent } } + size_t insertLastPressedSymbol( std::string & res, size_t pos, const Encoding::CodePage codePage ) const; + private: LocalEvent(); @@ -432,6 +441,25 @@ class LocalEvent std::pair>, std::optional>> _fingerIds; // Is the two-finger gesture currently being processed bool _isTwoFingerGestureInProgress = false; + + uint32_t _lastPressedCodePoint{ 0 }; +}; + +class TextInputEnabler +{ +public: + TextInputEnabler() + { + LocalEvent::enableTextInput(); + } + + TextInputEnabler( const TextInputEnabler & ) = delete; + TextInputEnabler & operator=( const TextInputEnabler & ) = delete; + + ~TextInputEnabler() + { + LocalEvent::disableTextInput(); + } }; #endif diff --git a/src/fheroes2/dialog/dialog_selectcount.cpp b/src/fheroes2/dialog/dialog_selectcount.cpp index f42791c201e..c16928430a7 100644 --- a/src/fheroes2/dialog/dialog_selectcount.cpp +++ b/src/fheroes2/dialog/dialog_selectcount.cpp @@ -31,6 +31,7 @@ #include #include "agg_image.h" +#include "char_encoding.h" #include "cursor.h" #include "dialog.h" #include "game_delays.h" @@ -47,6 +48,7 @@ #include "ui_button.h" #include "ui_dialog.h" #include "ui_keyboard.h" +#include "ui_language.h" #include "ui_text.h" #include "ui_tool.h" @@ -314,6 +316,10 @@ bool Dialog::InputString( const std::string & header, std::string & res, const s const bool isInGameKeyboardRequired = System::isVirtualKeyboardSupported(); + const TextInputEnabler textInputEnabler; + + const Encoding::CodePage codePage = fheroes2::getCodePage( fheroes2::getCurrentLanguage() ); + while ( le.HandleEvents( Game::isDelayNeeded( { Game::DelayType::CURSOR_BLINK_DELAY } ) ) ) { bool redraw = false; @@ -340,7 +346,7 @@ bool Dialog::InputString( const std::string & header, std::string & res, const s } else if ( le.KeyPress() ) { if ( charLimit == 0 || charLimit > res.size() || le.KeyValue() == fheroes2::Key::KEY_BACKSPACE ) { - charInsertPos = InsertKeySym( res, charInsertPos, le.KeyValue(), LocalEvent::getCurrentKeyModifiers() ); + charInsertPos = le.insertLastPressedSymbol( res, charInsertPos, codePage ); redraw = true; } } diff --git a/src/fheroes2/dialog/dialog_selectfile.cpp b/src/fheroes2/dialog/dialog_selectfile.cpp index 419fa93d23b..007676b0395 100644 --- a/src/fheroes2/dialog/dialog_selectfile.cpp +++ b/src/fheroes2/dialog/dialog_selectfile.cpp @@ -34,6 +34,7 @@ #include #include "agg_image.h" +#include "char_encoding.h" #include "cursor.h" #include "dialog.h" #include "dir.h" @@ -54,6 +55,7 @@ #include "ui_button.h" #include "ui_dialog.h" #include "ui_keyboard.h" +#include "ui_language.h" #include "ui_scrollbar.h" #include "ui_text.h" #include "ui_tool.h" @@ -408,8 +410,12 @@ namespace bool isCursorVisible = true; + const Encoding::CodePage codePage = fheroes2::getCodePage( fheroes2::getCurrentLanguage() ); + LocalEvent & le = LocalEvent::Get(); + const TextInputEnabler textInputEnabler; + while ( le.HandleEvents( !isEditing || Game::isDelayNeeded( { Game::DelayType::CURSOR_BLINK_DELAY } ) ) && result.empty() ) { le.MousePressLeft( buttonOk.area() ) && buttonOk.isEnabled() ? buttonOk.drawOnPress() : buttonOk.drawOnRelease(); le.MousePressLeft( buttonCancel.area() ) ? buttonCancel.drawOnPress() : buttonCancel.drawOnRelease(); @@ -464,7 +470,7 @@ namespace } else if ( !listboxEvent && le.KeyPress() && ( !isTextLimit || fheroes2::Key::KEY_BACKSPACE == le.KeyValue() || fheroes2::Key::KEY_DELETE == le.KeyValue() ) ) { - charInsertPos = InsertKeySym( filename, charInsertPos, le.KeyValue(), LocalEvent::getCurrentKeyModifiers() ); + charInsertPos = le.insertLastPressedSymbol( filename, charInsertPos, codePage ); if ( filename.empty() ) { buttonOk.disable(); } diff --git a/src/fheroes2/gui/ui_font.cpp b/src/fheroes2/gui/ui_font.cpp index ec07d28c9da..dd8f578673e 100644 --- a/src/fheroes2/gui/ui_font.cpp +++ b/src/fheroes2/gui/ui_font.cpp @@ -26,6 +26,7 @@ #include #include +#include "char_encoding.h" #include "icn.h" #include "image.h" #include "math_base.h" @@ -5743,49 +5744,38 @@ namespace fheroes2 { void generateAlphabet( const SupportedLanguage language, std::vector> & icnVsSprite ) { - switch ( language ) { - case SupportedLanguage::Czech: - case SupportedLanguage::Hungarian: - case SupportedLanguage::Polish: - case SupportedLanguage::Slovak: + const Encoding::CodePage codePage = getCodePage( language ); + + switch ( codePage ) { + case Encoding::CodePage::CP1250: generateCP1250Alphabet( icnVsSprite ); break; - case SupportedLanguage::Belarusian: - case SupportedLanguage::Bulgarian: - case SupportedLanguage::Russian: - case SupportedLanguage::Ukrainian: + case Encoding::CodePage::CP1251: generateCP1251Alphabet( icnVsSprite ); break; - case SupportedLanguage::Danish: - case SupportedLanguage::Dutch: - case SupportedLanguage::German: - case SupportedLanguage::Italian: - case SupportedLanguage::Norwegian: - case SupportedLanguage::Portuguese: - case SupportedLanguage::Spanish: - case SupportedLanguage::Swedish: - generateCP1252Alphabet( icnVsSprite ); - break; - case SupportedLanguage::French: + case Encoding::CodePage::CP1252: generateCP1252Alphabet( icnVsSprite ); - // This serves to make the font compatible with the original French custom encoding. - generateFrenchAlphabet( icnVsSprite ); break; - case SupportedLanguage::Turkish: + case Encoding::CodePage::CP1254: generateCP1254Alphabet( icnVsSprite ); break; - case SupportedLanguage::Vietnamese: + case Encoding::CodePage::CP1258: generateCP1258Alphabet( icnVsSprite ); break; - case SupportedLanguage::Romanian: + case Encoding::CodePage::ISO8859_16: generateISO8859_16Alphabet( icnVsSprite ); break; default: - // Add new language generation code! + // Add new a code font generation! assert( 0 ); break; } + if ( language == SupportedLanguage::French ) { + // This serves to make the font compatible with the original French custom encoding. + generateFrenchAlphabet( icnVsSprite ); + } + icnVsSprite[ICN::YELLOW_FONT].clear(); icnVsSprite[ICN::YELLOW_SMALLFONT].clear(); icnVsSprite[ICN::GRAY_FONT].clear(); @@ -5836,42 +5826,26 @@ namespace fheroes2 { generateGoodButtonFontBaseShape( icnVsSprite[ICN::BUTTON_GOOD_FONT_RELEASED] ); - switch ( language ) { - case SupportedLanguage::English: + const Encoding::CodePage codePage = getCodePage( language ); + + switch ( codePage ) { + case Encoding::CodePage::ASCII: generateBaseButtonFont( icnVsSprite[ICN::BUTTON_GOOD_FONT_RELEASED], icnVsSprite[ICN::BUTTON_GOOD_FONT_PRESSED], icnVsSprite[ICN::BUTTON_EVIL_FONT_RELEASED], icnVsSprite[ICN::BUTTON_EVIL_FONT_PRESSED] ); return; - case SupportedLanguage::Czech: - case SupportedLanguage::Hungarian: - case SupportedLanguage::Polish: - case SupportedLanguage::Slovak: + case Encoding::CodePage::CP1250: generateCP1250GoodButtonFont( icnVsSprite[ICN::BUTTON_GOOD_FONT_RELEASED] ); break; - case SupportedLanguage::Belarusian: - case SupportedLanguage::Bulgarian: - case SupportedLanguage::Russian: - case SupportedLanguage::Ukrainian: + case Encoding::CodePage::CP1251: generateCP1251GoodButtonFont( icnVsSprite[ICN::BUTTON_GOOD_FONT_RELEASED] ); break; - case SupportedLanguage::Danish: - case SupportedLanguage::Dutch: - case SupportedLanguage::French: - case SupportedLanguage::German: - case SupportedLanguage::Italian: - case SupportedLanguage::Norwegian: - case SupportedLanguage::Portuguese: - case SupportedLanguage::Spanish: - case SupportedLanguage::Swedish: + case Encoding::CodePage::CP1252: generateCP1252GoodButtonFont( icnVsSprite[ICN::BUTTON_GOOD_FONT_RELEASED] ); break; - case SupportedLanguage::Turkish: - // generateGoodCP1254ButtonFont( icnVsSprite[ICN::BUTTON_GOOD_FONT_RELEASED] ); - break; - case SupportedLanguage::Vietnamese: - // generateGoodCP1258ButtonFont( icnVsSprite[ICN::BUTTON_GOOD_FONT_RELEASED] ); - break; - case SupportedLanguage::Romanian: - // generateGoodISO8859_16ButtonFont( icnVsSprite[ICN::BUTTON_GOOD_FONT_RELEASED] ); + case Encoding::CodePage::CP1254: + case Encoding::CodePage::CP1258: + case Encoding::CodePage::ISO8859_16: + // TODO: no buttons are generated yet for these code pages. break; default: // Add new language generation code! diff --git a/src/fheroes2/gui/ui_language.cpp b/src/fheroes2/gui/ui_language.cpp index 6d6f279e6a5..f1286730545 100644 --- a/src/fheroes2/gui/ui_language.cpp +++ b/src/fheroes2/gui/ui_language.cpp @@ -71,6 +71,46 @@ namespace namespace fheroes2 { + Encoding::CodePage getCodePage( const SupportedLanguage language ) + { + switch ( language ) { + case SupportedLanguage::English: + return Encoding::CodePage::ASCII; + case SupportedLanguage::Czech: + case SupportedLanguage::Hungarian: + case SupportedLanguage::Polish: + case SupportedLanguage::Slovak: + return Encoding::CodePage::CP1250; + case SupportedLanguage::Belarusian: + case SupportedLanguage::Bulgarian: + case SupportedLanguage::Russian: + case SupportedLanguage::Ukrainian: + return Encoding::CodePage::CP1251; + case SupportedLanguage::Danish: + case SupportedLanguage::Dutch: + case SupportedLanguage::French: + case SupportedLanguage::German: + case SupportedLanguage::Italian: + case SupportedLanguage::Norwegian: + case SupportedLanguage::Portuguese: + case SupportedLanguage::Spanish: + case SupportedLanguage::Swedish: + return Encoding::CodePage::CP1252; + case SupportedLanguage::Turkish: + return Encoding::CodePage::CP1254; + case SupportedLanguage::Vietnamese: + return Encoding::CodePage::CP1258; + case SupportedLanguage::Romanian: + return Encoding::CodePage::ISO8859_16; + default: + // Add new language generation code! + assert( 0 ); + break; + } + + return Encoding::CodePage::ASCII; + } + LanguageSwitcher::LanguageSwitcher( const SupportedLanguage language ) : _currentLanguage( Settings::Get().getGameLanguage() ) { diff --git a/src/fheroes2/gui/ui_language.h b/src/fheroes2/gui/ui_language.h index 347523404f6..b75698455a6 100644 --- a/src/fheroes2/gui/ui_language.h +++ b/src/fheroes2/gui/ui_language.h @@ -23,6 +23,8 @@ #include #include +#include "char_encoding.h" + namespace fheroes2 { enum class SupportedLanguage : int @@ -52,6 +54,8 @@ namespace fheroes2 Vietnamese }; + Encoding::CodePage getCodePage( const SupportedLanguage language ); + class LanguageSwitcher { public: