trunk/src/emu/language.cpp
| r0 | r253582 | |
| 1 | // license:BSD-3-Clause |
| 2 | // copyright-holders:Miodrag Milanovic |
| 3 | /*************************************************************************** |
| 4 | |
| 5 | language.cpp |
| 6 | |
| 7 | Multi-language support. |
| 8 | |
| 9 | ***************************************************************************/ |
| 10 | |
| 11 | #include "language.h" |
| 12 | |
| 13 | static std::unordered_map<std::string, std::string> g_translation; |
| 14 | |
| 15 | const char *lang_translate(const char *word) |
| 16 | { |
| 17 | if (g_translation.find(word) == g_translation.end()) |
| 18 | { |
| 19 | return word; |
| 20 | } |
| 21 | return g_translation[word].c_str(); |
| 22 | } |
| 23 | |
| 24 | const UINT32 MO_MAGIC = 0x950412de; |
| 25 | const UINT32 MO_MAGIC_REVERSED = 0xde120495; |
| 26 | |
| 27 | inline UINT32 endianchange(UINT32 value) { |
| 28 | UINT32 b0 = (value >> 0) & 0xff; |
| 29 | UINT32 b1 = (value >> 8) & 0xff; |
| 30 | UINT32 b2 = (value >> 16) & 0xff; |
| 31 | UINT32 b3 = (value >> 24) & 0xff; |
| 32 | |
| 33 | return (b0 << 24) | (b1 << 16) | (b2 << 8) | b3; |
| 34 | } |
| 35 | |
| 36 | void load_translation(emu_options &m_options) |
| 37 | { |
| 38 | g_translation.clear(); |
| 39 | emu_file file(m_options.language_path(), OPEN_FLAG_READ); |
| 40 | if (file.open(m_options.language(), PATH_SEPARATOR "strings.mo") == FILERR_NONE) |
| 41 | { |
| 42 | UINT64 size = file.size(); |
| 43 | UINT32 *buffer = global_alloc_array(UINT32, size / 4 + 1); |
| 44 | file.read(buffer, size); |
| 45 | file.close(); |
| 46 | |
| 47 | if (buffer[0] != MO_MAGIC && buffer[0] != MO_MAGIC_REVERSED) |
| 48 | { |
| 49 | global_free_array(buffer); |
| 50 | return; |
| 51 | } |
| 52 | if (buffer[0] == MO_MAGIC_REVERSED) |
| 53 | { |
| 54 | for (auto i = 0; i < (size / 4) + 1; ++i) |
| 55 | { |
| 56 | buffer[i] = endianchange(buffer[i]); |
| 57 | } |
| 58 | } |
| 59 | |
| 60 | UINT32 number_of_strings = buffer[2]; |
| 61 | UINT32 original_table_offset = buffer[3] >> 2; |
| 62 | UINT32 translation_table_offset = buffer[4] >> 2; |
| 63 | |
| 64 | const char *data = reinterpret_cast<const char*>(buffer); |
| 65 | |
| 66 | for (auto i = 1; i < number_of_strings; ++i) |
| 67 | { |
| 68 | std::string original = (const char *)data + buffer[original_table_offset + 2 * i + 1]; |
| 69 | std::string translation = (const char *)data + buffer[translation_table_offset + 2 * i + 1]; |
| 70 | g_translation.insert(std::pair<std::string, std::string>(original, translation)); |
| 71 | } |
| 72 | global_free_array(buffer); |
| 73 | } |
| 74 | } |
| | No newline at end of file |
trunk/src/emu/ui/custui.cpp
| r253581 | r253582 | |
| 15 | 15 | #include "ui/custui.h" |
| 16 | 16 | #include "ui/utils.h" |
| 17 | 17 | #include <algorithm> |
| 18 | #include "language.h" |
| 18 | 19 | |
| 19 | 20 | const char *ui_menu_custom_ui::hide_status[] = { "Show All", "Hide Filters", "Hide Info/Image", "Hide Both" }; |
| 20 | 21 | |
| r253581 | r253582 | |
| 24 | 25 | |
| 25 | 26 | ui_menu_custom_ui::ui_menu_custom_ui(running_machine &machine, render_container *container) : ui_menu(machine, container) |
| 26 | 27 | { |
| 28 | // load languages |
| 29 | file_enumerator path(machine.options().language_path()); |
| 30 | const char *lang = machine.options().language(); |
| 31 | const osd_directory_entry *dirent; |
| 32 | for (int x = 0; (dirent = path.next()) != nullptr; ++x) |
| 33 | if (dirent->type == ENTTYPE_DIR && strcmp(dirent->name, ".") != 0 && strcmp(dirent->name, "..") != 0) |
| 34 | { |
| 35 | m_lang.push_back(dirent->name); |
| 36 | if (strcmp(dirent->name, lang) == 0) |
| 37 | m_currlang = x; |
| 38 | } |
| 27 | 39 | } |
| 28 | 40 | |
| 29 | 41 | //------------------------------------------------- |
| r253581 | r253582 | |
| 34 | 46 | { |
| 35 | 47 | std::string error_string; |
| 36 | 48 | machine().ui().options().set_value(OPTION_HIDE_PANELS, ui_globals::panels_status, OPTION_PRIORITY_CMDLINE, error_string); |
| 49 | if (!m_lang.empty()) |
| 50 | { |
| 51 | machine().options().set_value(OPTION_LANGUAGE, m_lang[m_currlang].c_str(), OPTION_PRIORITY_CMDLINE, error_string); |
| 52 | load_translation(machine().options()); |
| 53 | } |
| 37 | 54 | ui_globals::reset = true; |
| 38 | 55 | } |
| 39 | 56 | |
| r253581 | r253582 | |
| 50 | 67 | |
| 51 | 68 | if (m_event != nullptr && m_event->itemref != nullptr) |
| 52 | 69 | { |
| 53 | | if (m_event->iptkey == IPT_UI_LEFT || m_event->iptkey == IPT_UI_RIGHT) |
| 70 | switch ((FPTR)m_event->itemref) |
| 54 | 71 | { |
| 55 | | changed = true; |
| 56 | | (m_event->iptkey == IPT_UI_RIGHT) ? ui_globals::panels_status++ : ui_globals::panels_status--; |
| 57 | | } |
| 58 | | |
| 59 | | |
| 60 | | else if (m_event->iptkey == IPT_UI_SELECT) |
| 61 | | { |
| 62 | | switch ((FPTR)m_event->itemref) |
| 63 | | { |
| 64 | | case FONT_MENU: |
| 72 | case FONT_MENU: |
| 73 | if (m_event->iptkey == IPT_UI_SELECT) |
| 65 | 74 | ui_menu::stack_push(global_alloc_clear<ui_menu_font_ui>(machine(), container)); |
| 66 | | break; |
| 67 | | |
| 68 | | case COLORS_MENU: |
| 75 | break; |
| 76 | case COLORS_MENU: |
| 77 | if (m_event->iptkey == IPT_UI_SELECT) |
| 69 | 78 | ui_menu::stack_push(global_alloc_clear<ui_menu_colors_ui>(machine(), container)); |
| 70 | | break; |
| 71 | | case HIDE_MENU: |
| 79 | break; |
| 80 | case HIDE_MENU: |
| 81 | { |
| 82 | if (m_event->iptkey == IPT_UI_LEFT || m_event->iptkey == IPT_UI_RIGHT) |
| 72 | 83 | { |
| 84 | changed = true; |
| 85 | (m_event->iptkey == IPT_UI_RIGHT) ? ui_globals::panels_status++ : ui_globals::panels_status--; |
| 86 | } |
| 87 | else if (m_event->iptkey == IPT_UI_SELECT) |
| 88 | { |
| 73 | 89 | int total = ARRAY_LENGTH(hide_status); |
| 74 | 90 | std::vector<std::string> s_sel(total); |
| 75 | 91 | for (int index = 0; index < total; ++index) |
| r253581 | r253582 | |
| 78 | 94 | ui_menu::stack_push(global_alloc_clear<ui_menu_selector>(machine(), container, s_sel, ui_globals::panels_status)); |
| 79 | 95 | } |
| 80 | 96 | } |
| 97 | case LANGUAGE_MENU: |
| 98 | { |
| 99 | if (m_event->iptkey == IPT_UI_LEFT || m_event->iptkey == IPT_UI_RIGHT) |
| 100 | { |
| 101 | changed = true; |
| 102 | (m_event->iptkey == IPT_UI_RIGHT) ? m_currlang++ : m_currlang--; |
| 103 | } |
| 104 | else if (m_event->iptkey == IPT_UI_SELECT) |
| 105 | { |
| 106 | int total = m_lang.size(); |
| 107 | std::vector<std::string> s_sel(total); |
| 108 | for (int index = 0; index < total; ++index) |
| 109 | s_sel[index] = m_lang[index]; |
| 110 | |
| 111 | ui_menu::stack_push(global_alloc_clear<ui_menu_selector>(machine(), container, s_sel, m_currlang)); |
| 112 | } |
| 113 | } |
| 81 | 114 | } |
| 82 | 115 | } |
| 83 | 116 | |
| r253581 | r253582 | |
| 91 | 124 | |
| 92 | 125 | void ui_menu_custom_ui::populate() |
| 93 | 126 | { |
| 127 | UINT32 arrow_flags; |
| 94 | 128 | item_append("Fonts", nullptr, 0, (void *)(FPTR)FONT_MENU); |
| 95 | 129 | item_append("Colors", nullptr, 0, (void *)(FPTR)COLORS_MENU); |
| 96 | 130 | |
| 97 | | UINT32 arrow_flags = get_arrow_flags(0, (int)HIDE_BOTH, ui_globals::panels_status); |
| 98 | | item_append("Filters and Info/Image", hide_status[ui_globals::panels_status], arrow_flags, (void *)(FPTR)HIDE_MENU); |
| 131 | if (!m_lang.empty()) |
| 132 | { |
| 133 | arrow_flags = get_arrow_flags(0, m_lang.size() - 1, m_currlang); |
| 134 | item_append("Language", m_lang[m_currlang].c_str(), arrow_flags, (void *)(FPTR)LANGUAGE_MENU); |
| 135 | } |
| 99 | 136 | |
| 137 | arrow_flags = get_arrow_flags(0, (int)HIDE_BOTH, ui_globals::panels_status); |
| 138 | item_append("Show side panels", hide_status[ui_globals::panels_status], arrow_flags, (void *)(FPTR)HIDE_MENU); |
| 139 | |
| 100 | 140 | item_append(MENU_SEPARATOR_ITEM, nullptr, 0, nullptr); |
| 101 | 141 | customtop = machine().ui().get_line_height() + 3.0f * UI_BOX_TB_BORDER; |
| 102 | 142 | } |