630 lines
18 KiB
C++
630 lines
18 KiB
C++
/*
|
|
* Copyright 2010, Stephan Aßmus <superstippi@gmx.de>
|
|
* Copyright 2010-2021, Adrien Destugues, pulkomandy@pulkomandy.tk.
|
|
* Copyright 2011, Axel Dörfler, axeld@pinc-software.de.
|
|
* Copyright 2020-2021, Panagiotis Vasilopoulos <hello@alwayslivid.com>
|
|
*
|
|
* All rights reserved. Distributed under the terms of the MIT License.
|
|
*/
|
|
|
|
|
|
#include "BootPromptWindow.h"
|
|
|
|
#include <new>
|
|
#include <stdio.h>
|
|
|
|
#include <Alert.h>
|
|
#include <Bitmap.h>
|
|
#include <Button.h>
|
|
#include <Catalog.h>
|
|
#include <ControlLook.h>
|
|
#include <Directory.h>
|
|
#include <Entry.h>
|
|
#include <Font.h>
|
|
#include <FindDirectory.h>
|
|
#include <File.h>
|
|
#include <FormattingConventions.h>
|
|
#include <IconUtils.h>
|
|
#include <IconView.h>
|
|
#include <LayoutBuilder.h>
|
|
#include <ListView.h>
|
|
#include <Locale.h>
|
|
#include <Menu.h>
|
|
#include <MutableLocaleRoster.h>
|
|
#include <ObjectList.h>
|
|
#include <Path.h>
|
|
#include <Roster.h>
|
|
#include <Screen.h>
|
|
#include <ScrollView.h>
|
|
#include <SeparatorView.h>
|
|
#include <StringItem.h>
|
|
#include <StringView.h>
|
|
#include <TextView.h>
|
|
#include <UnicodeChar.h>
|
|
|
|
#include "BootPrompt.h"
|
|
#include "Keymap.h"
|
|
#include "KeymapNames.h"
|
|
|
|
|
|
using BPrivate::MutableLocaleRoster;
|
|
|
|
|
|
#undef B_TRANSLATION_CONTEXT
|
|
#define B_TRANSLATION_CONTEXT "BootPromptWindow"
|
|
|
|
|
|
namespace BPrivate {
|
|
void ForceUnloadCatalog();
|
|
};
|
|
|
|
|
|
static const char* kLanguageKeymapMappings[] = {
|
|
// While there is a "Dutch" keymap, it apparently has not been widely
|
|
// adopted, and the US-International keymap is common
|
|
"Dutch", "US-International",
|
|
|
|
// Cyrillic keymaps are not usable alone, as latin alphabet is required to
|
|
// use Terminal. So we stay in US international until the user has a chance
|
|
// to set up KeymapSwitcher.
|
|
"Belarusian", "US-International",
|
|
"Russian", "US-International",
|
|
"Ukrainian", "US-International",
|
|
|
|
// Turkish has two layouts, we must pick one
|
|
"Turkish", "Turkish (Type-Q)",
|
|
};
|
|
static const size_t kLanguageKeymapMappingsSize
|
|
= sizeof(kLanguageKeymapMappings) / sizeof(kLanguageKeymapMappings[0]);
|
|
|
|
|
|
class LanguageItem : public BStringItem {
|
|
public:
|
|
LanguageItem(const char* label, const char* language)
|
|
:
|
|
BStringItem(label),
|
|
fLanguage(language)
|
|
{
|
|
}
|
|
|
|
~LanguageItem()
|
|
{
|
|
}
|
|
|
|
const char* Language() const
|
|
{
|
|
return fLanguage.String();
|
|
}
|
|
|
|
void DrawItem(BView* owner, BRect frame, bool complete)
|
|
{
|
|
BStringItem::DrawItem(owner, frame, true/*complete*/);
|
|
}
|
|
|
|
private:
|
|
BString fLanguage;
|
|
};
|
|
|
|
|
|
static int
|
|
compare_void_list_items(const void* _a, const void* _b)
|
|
{
|
|
static BCollator collator;
|
|
|
|
LanguageItem* a = *(LanguageItem**)_a;
|
|
LanguageItem* b = *(LanguageItem**)_b;
|
|
|
|
return collator.Compare(a->Text(), b->Text());
|
|
}
|
|
|
|
|
|
static int
|
|
compare_void_menu_items(const void* _a, const void* _b)
|
|
{
|
|
static BCollator collator;
|
|
|
|
BMenuItem* a = *(BMenuItem**)_a;
|
|
BMenuItem* b = *(BMenuItem**)_b;
|
|
|
|
return collator.Compare(a->Label(), b->Label());
|
|
}
|
|
|
|
|
|
// #pragma mark -
|
|
|
|
|
|
BootPromptWindow::BootPromptWindow()
|
|
:
|
|
BWindow(BRect(0, 0, 530, 400), "",
|
|
B_TITLED_WINDOW, B_NOT_ZOOMABLE | B_NOT_MINIMIZABLE | B_NOT_RESIZABLE
|
|
| B_AUTO_UPDATE_SIZE_LIMITS | B_QUIT_ON_WINDOW_CLOSE,
|
|
B_ALL_WORKSPACES),
|
|
fDefaultKeymapItem(NULL)
|
|
{
|
|
SetSizeLimits(450, 16384, 350, 16384);
|
|
|
|
rgb_color textColor = ui_color(B_PANEL_TEXT_COLOR);
|
|
fInfoTextView = new BTextView("");
|
|
fInfoTextView->SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
|
|
fInfoTextView->SetFontAndColor(be_plain_font, B_FONT_ALL, &textColor);
|
|
fInfoTextView->MakeEditable(false);
|
|
fInfoTextView->MakeSelectable(false);
|
|
fInfoTextView->MakeResizable(false);
|
|
|
|
BResources* res = BApplication::AppResources();
|
|
size_t size = 0;
|
|
const uint8_t* data;
|
|
|
|
BBitmap desktopIcon(BRect(0, 0, 23, 23), B_RGBA32);
|
|
data = (const uint8_t*)res->LoadResource('VICN', "Desktop", &size);
|
|
BIconUtils::GetVectorIcon(data, size, &desktopIcon);
|
|
|
|
BBitmap installerIcon(BRect(0, 0, 23, 23), B_RGBA32);
|
|
data = (const uint8_t*)res->LoadResource('VICN', "Installer", &size);
|
|
BIconUtils::GetVectorIcon(data, size, &installerIcon);
|
|
|
|
fDesktopButton = new BButton("", new BMessage(MSG_BOOT_DESKTOP));
|
|
fDesktopButton->SetTarget(be_app);
|
|
fDesktopButton->MakeDefault(true);
|
|
fDesktopButton->SetIcon(&desktopIcon);
|
|
|
|
fInstallerButton = new BButton("", new BMessage(MSG_RUN_INSTALLER));
|
|
fInstallerButton->SetTarget(be_app);
|
|
fInstallerButton->SetIcon(&installerIcon);
|
|
|
|
data = (const uint8_t*)res->LoadResource('VICN', "Language", &size);
|
|
IconView* languageIcon = new IconView(B_LARGE_ICON);
|
|
languageIcon->SetIcon(data, size, B_LARGE_ICON);
|
|
|
|
data = (const uint8_t*)res->LoadResource('VICN', "Keymap", &size);
|
|
IconView* keymapIcon = new IconView(B_LARGE_ICON);
|
|
keymapIcon->SetIcon(data, size, B_LARGE_ICON);
|
|
|
|
fLanguagesLabelView = new BStringView("languagesLabel", "");
|
|
fLanguagesLabelView->SetFont(be_bold_font);
|
|
fLanguagesLabelView->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED,
|
|
B_SIZE_UNSET));
|
|
|
|
fKeymapsMenuLabel = new BStringView("keymapsLabel", "");
|
|
fKeymapsMenuLabel->SetFont(be_bold_font);
|
|
fKeymapsMenuLabel->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED,
|
|
B_SIZE_UNSET));
|
|
// Make sure there is enough space to display the text even in verbose
|
|
// locales, to avoid width changes on language changes
|
|
float labelWidth = fKeymapsMenuLabel->StringWidth("Disposition du clavier")
|
|
+ 16;
|
|
fKeymapsMenuLabel->SetExplicitMinSize(BSize(labelWidth, B_SIZE_UNSET));
|
|
|
|
fLanguagesListView = new BListView();
|
|
BScrollView* languagesScrollView = new BScrollView("languagesScroll",
|
|
fLanguagesListView, B_WILL_DRAW, false, true);
|
|
|
|
// Carefully designed to not exceed the 640x480 resolution with a 12pt font.
|
|
float width = 640 * be_plain_font->Size() / 12 - (labelWidth + 64);
|
|
float height = be_plain_font->Size() * 23;
|
|
fInfoTextView->SetExplicitMinSize(BSize(width, height));
|
|
fInfoTextView->SetExplicitMaxSize(BSize(width, B_SIZE_UNSET));
|
|
|
|
// Make sure the language list view is always wide enough to show the
|
|
// largest language
|
|
fLanguagesListView->SetExplicitMinSize(
|
|
BSize(fLanguagesListView->StringWidth("Português (Brasil)"),
|
|
height));
|
|
|
|
fKeymapsMenuField = new BMenuField("", "", new BMenu(""));
|
|
fKeymapsMenuField->Menu()->SetLabelFromMarked(true);
|
|
|
|
_InitCatalog(true);
|
|
_PopulateLanguages();
|
|
_PopulateKeymaps();
|
|
|
|
BLayoutBuilder::Group<>(this, B_HORIZONTAL)
|
|
.SetInsets(B_USE_WINDOW_SPACING)
|
|
.AddGroup(B_VERTICAL, 0)
|
|
.SetInsets(0, 0, 0, B_USE_SMALL_SPACING)
|
|
.AddGroup(B_HORIZONTAL)
|
|
.Add(languageIcon)
|
|
.Add(fLanguagesLabelView)
|
|
.SetInsets(0, 0, 0, B_USE_SMALL_SPACING)
|
|
.End()
|
|
.Add(languagesScrollView)
|
|
.AddGroup(B_HORIZONTAL)
|
|
.Add(keymapIcon)
|
|
.Add(fKeymapsMenuLabel)
|
|
.SetInsets(0, B_USE_DEFAULT_SPACING, 0,
|
|
B_USE_SMALL_SPACING)
|
|
.End()
|
|
.Add(fKeymapsMenuField)
|
|
.End()
|
|
.AddGroup(B_VERTICAL)
|
|
.SetInsets(0)
|
|
.Add(fInfoTextView)
|
|
.AddGroup(B_HORIZONTAL)
|
|
.SetInsets(0)
|
|
.AddGlue()
|
|
.Add(fInstallerButton)
|
|
.Add(fDesktopButton)
|
|
.End()
|
|
.End();
|
|
|
|
fLanguagesListView->MakeFocus();
|
|
|
|
// Force the info text view to use a reasonable size
|
|
fInfoTextView->SetText("x\n\n\n\n\n\n\n\n\n\n\n\n\n\nx");
|
|
ResizeToPreferred();
|
|
|
|
_UpdateStrings();
|
|
CenterOnScreen();
|
|
Show();
|
|
}
|
|
|
|
|
|
void
|
|
BootPromptWindow::MessageReceived(BMessage* message)
|
|
{
|
|
switch (message->what) {
|
|
case MSG_LANGUAGE_SELECTED:
|
|
if (LanguageItem* item = static_cast<LanguageItem*>(
|
|
fLanguagesListView->ItemAt(
|
|
fLanguagesListView->CurrentSelection(0)))) {
|
|
BMessage preferredLanguages;
|
|
preferredLanguages.AddString("language", item->Language());
|
|
MutableLocaleRoster::Default()->SetPreferredLanguages(
|
|
&preferredLanguages);
|
|
_InitCatalog(true);
|
|
_UpdateKeymapsMenu();
|
|
|
|
// Select default keymap by language
|
|
BLanguage language(item->Language());
|
|
BMenuItem* keymapItem = _KeymapItemForLanguage(language);
|
|
if (keymapItem != NULL) {
|
|
keymapItem->SetMarked(true);
|
|
_ActivateKeymap(keymapItem->Message());
|
|
}
|
|
}
|
|
// Calling it here is a cheap way of preventing the user to have
|
|
// no item selected. Always the current item will be selected.
|
|
_UpdateStrings();
|
|
break;
|
|
|
|
case MSG_KEYMAP_SELECTED:
|
|
_ActivateKeymap(message);
|
|
break;
|
|
|
|
default:
|
|
BWindow::MessageReceived(message);
|
|
}
|
|
}
|
|
|
|
|
|
bool
|
|
BootPromptWindow::QuitRequested()
|
|
{
|
|
// If the Deskbar is not running, then FirstBootPrompt is
|
|
// is the only thing visible on the screen and that we won't
|
|
// have anything else to show. In that case, it would make
|
|
// sense to reboot the machine instead, but doing so without
|
|
// a warning could be confusing.
|
|
//
|
|
// Rebooting is managed by BootPrompt.cpp.
|
|
|
|
BAlert* alert = new(std::nothrow) BAlert(
|
|
B_TRANSLATE_SYSTEM_NAME("Quit Haiku"),
|
|
B_TRANSLATE("Are you sure you want to close this window? This will "
|
|
"restart your system!"),
|
|
B_TRANSLATE("Cancel"), B_TRANSLATE("Restart system"), NULL,
|
|
B_WIDTH_AS_USUAL, B_STOP_ALERT);
|
|
|
|
// If there is not enough memory to create the alert here, we may as
|
|
// well try to reboot. There probably isn't much else to do anyway.
|
|
if (alert != NULL) {
|
|
alert->SetShortcut(0, B_ESCAPE);
|
|
|
|
if (alert->Go() == 0) {
|
|
// User doesn't want to exit after all
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// If deskbar is running, don't actually reboot: we are in test mode
|
|
// (probably run by a developer manually).
|
|
if (!be_roster->IsRunning(kDeskbarSignature))
|
|
be_app->PostMessage(MSG_REBOOT_REQUESTED);
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
void
|
|
BootPromptWindow::_InitCatalog(bool saveSettings)
|
|
{
|
|
// Initilialize the Locale Kit
|
|
BPrivate::ForceUnloadCatalog();
|
|
|
|
if (!saveSettings)
|
|
return;
|
|
|
|
BMessage settings;
|
|
BString language;
|
|
if (BLocaleRoster::Default()->GetCatalog()->GetLanguage(&language) == B_OK)
|
|
settings.AddString("language", language.String());
|
|
|
|
MutableLocaleRoster::Default()->SetPreferredLanguages(&settings);
|
|
|
|
BFormattingConventions conventions(language.String());
|
|
MutableLocaleRoster::Default()->SetDefaultFormattingConventions(
|
|
conventions);
|
|
}
|
|
|
|
|
|
void
|
|
BootPromptWindow::_UpdateStrings()
|
|
{
|
|
BString titleTextHaiku = B_TRANSLATE("Welcome to Haiku!");
|
|
BString mainTextHaiku = B_TRANSLATE_COMMENT(
|
|
"Thank you for trying out Haiku! We hope you'll like it!\n\n"
|
|
"Please select your preferred language and keymap. Both settings can "
|
|
"also be changed later when running Haiku.\n\n"
|
|
|
|
"Do you wish to install Haiku now, or try it out first?",
|
|
|
|
"For other languages, a note could be added: \""
|
|
"Note: Localization of Haiku applications and other components is "
|
|
"an on-going effort. You will frequently encounter untranslated "
|
|
"strings, but if you like, you can join in the work at "
|
|
"<www.haiku-os.org>.\"");
|
|
BString desktopTextHaiku = B_TRANSLATE("Try Haiku");
|
|
BString installTextHaiku = B_TRANSLATE("Install Haiku");
|
|
|
|
BString titleTextDebranded = B_TRANSLATE("Welcome!");
|
|
BString mainTextDebranded = B_TRANSLATE_COMMENT(
|
|
"Thank you for trying out our operating system! We hope you'll "
|
|
"like it!\n\n"
|
|
"Please select your preferred language and keymap. Both settings "
|
|
"can also be changed later.\n\n"
|
|
|
|
"Do you wish to install the operating system now, or try it out "
|
|
"first?",
|
|
|
|
"This notice appears when the build of Haiku that's currently "
|
|
"being used is unofficial, as in, not distributed by Haiku itself."
|
|
"For other languages, a note could be added: \""
|
|
"Note: Localization of Haiku applications and other components is "
|
|
"an on-going effort. You will frequently encounter untranslated "
|
|
"strings, but if you like, you can join in the work at "
|
|
"<www.haiku-os.org>.\"");
|
|
BString desktopTextDebranded = B_TRANSLATE("Try it out");
|
|
BString installTextDebranded = B_TRANSLATE("Install");
|
|
|
|
#ifdef HAIKU_DISTRO_COMPATIBILITY_OFFICIAL
|
|
SetTitle(titleTextHaiku);
|
|
fInfoTextView->SetText(mainTextHaiku);
|
|
fDesktopButton->SetLabel(desktopTextHaiku);
|
|
fInstallerButton->SetLabel(installTextHaiku);
|
|
#else
|
|
SetTitle(titleTextDebranded);
|
|
fInfoTextView->SetText(mainTextDebranded);
|
|
fDesktopButton->SetLabel(desktopTextDebranded);
|
|
fInstallerButton->SetLabel(installTextDebranded);
|
|
#endif
|
|
|
|
fLanguagesLabelView->SetText(B_TRANSLATE("Language"));
|
|
fKeymapsMenuLabel->SetText(B_TRANSLATE("Keymap"));
|
|
if (fKeymapsMenuField->Menu()->FindMarked() == NULL)
|
|
fKeymapsMenuField->MenuItem()->SetLabel(B_TRANSLATE("Custom"));
|
|
}
|
|
|
|
|
|
void
|
|
BootPromptWindow::_PopulateLanguages()
|
|
{
|
|
// TODO: detect language/country from IP address
|
|
|
|
// Get current first preferred language of the user
|
|
BMessage preferredLanguages;
|
|
BLocaleRoster::Default()->GetPreferredLanguages(&preferredLanguages);
|
|
const char* firstPreferredLanguage;
|
|
if (preferredLanguages.FindString("language", &firstPreferredLanguage)
|
|
!= B_OK) {
|
|
// Fall back to built-in language of this application.
|
|
firstPreferredLanguage = "en";
|
|
}
|
|
|
|
BMessage installedCatalogs;
|
|
BLocaleRoster::Default()->GetAvailableCatalogs(&installedCatalogs,
|
|
"x-vnd.Haiku-FirstBootPrompt");
|
|
|
|
BFont font;
|
|
fLanguagesListView->GetFont(&font);
|
|
|
|
// Try to instantiate a BCatalog for each language, it will only work
|
|
// for translations of this application. So the list of languages will be
|
|
// limited to catalogs written for this application, which is on purpose!
|
|
|
|
const char* languageID;
|
|
LanguageItem* currentItem = NULL;
|
|
for (int32 i = 0; installedCatalogs.FindString("language", i, &languageID)
|
|
== B_OK; i++) {
|
|
BLanguage* language;
|
|
if (BLocaleRoster::Default()->GetLanguage(languageID, &language)
|
|
== B_OK) {
|
|
BString name;
|
|
language->GetNativeName(name);
|
|
|
|
// TODO: the following block fails to detect a couple of language
|
|
// names as containing glyphs we can't render. Why's that?
|
|
bool hasGlyphs[name.CountChars()];
|
|
font.GetHasGlyphs(name.String(), name.CountChars(), hasGlyphs);
|
|
for (int32 i = 0; i < name.CountChars(); ++i) {
|
|
if (!hasGlyphs[i]) {
|
|
// replace by name translated to current language
|
|
language->GetName(name);
|
|
break;
|
|
}
|
|
}
|
|
|
|
LanguageItem* item = new LanguageItem(name.String(),
|
|
languageID);
|
|
fLanguagesListView->AddItem(item);
|
|
// Select this item if it is the first preferred language
|
|
if (strcmp(firstPreferredLanguage, languageID) == 0)
|
|
currentItem = item;
|
|
|
|
delete language;
|
|
} else
|
|
fprintf(stderr, "failed to get BLanguage for %s\n", languageID);
|
|
}
|
|
|
|
fLanguagesListView->SortItems(compare_void_list_items);
|
|
if (currentItem != NULL)
|
|
fLanguagesListView->Select(fLanguagesListView->IndexOf(currentItem));
|
|
fLanguagesListView->ScrollToSelection();
|
|
|
|
// Re-enable sending the selection message.
|
|
fLanguagesListView->SetSelectionMessage(
|
|
new BMessage(MSG_LANGUAGE_SELECTED));
|
|
}
|
|
|
|
|
|
void
|
|
BootPromptWindow::_UpdateKeymapsMenu()
|
|
{
|
|
BMenu *menu = fKeymapsMenuField->Menu();
|
|
BMenuItem* item;
|
|
BList itemsList;
|
|
|
|
// Recreate keymapmenu items list, since BMenu could not sort its items.
|
|
while ((item = menu->ItemAt(0)) != NULL) {
|
|
BMessage* message = item->Message();
|
|
entry_ref ref;
|
|
message->FindRef("ref", &ref);
|
|
item-> SetLabel(B_TRANSLATE_NOCOLLECT_ALL((ref.name),
|
|
"KeymapNames", NULL));
|
|
itemsList.AddItem(item);
|
|
menu->RemoveItem((int32)0);
|
|
}
|
|
itemsList.SortItems(compare_void_menu_items);
|
|
fKeymapsMenuField->Menu()->AddList(&itemsList, 0);
|
|
}
|
|
|
|
|
|
void
|
|
BootPromptWindow::_PopulateKeymaps()
|
|
{
|
|
// Get the name of the current keymap, so we can mark the correct entry
|
|
// in the list view.
|
|
BString currentName;
|
|
entry_ref currentRef;
|
|
if (_GetCurrentKeymapRef(currentRef) == B_OK) {
|
|
BNode node(¤tRef);
|
|
node.ReadAttrString("keymap:name", ¤tName);
|
|
}
|
|
|
|
// TODO: common keymaps!
|
|
BPath path;
|
|
if (find_directory(B_SYSTEM_DATA_DIRECTORY, &path) != B_OK
|
|
|| path.Append("Keymaps") != B_OK) {
|
|
return;
|
|
}
|
|
|
|
// US-International is the default keymap, if we could not found a
|
|
// matching one
|
|
BString usInternational("US-International");
|
|
|
|
// Populate the menu
|
|
BDirectory directory;
|
|
if (directory.SetTo(path.Path()) == B_OK) {
|
|
entry_ref ref;
|
|
BList itemsList;
|
|
while (directory.GetNextRef(&ref) == B_OK) {
|
|
BMessage* message = new BMessage(MSG_KEYMAP_SELECTED);
|
|
message->AddRef("ref", &ref);
|
|
BMenuItem* item =
|
|
new BMenuItem(B_TRANSLATE_NOCOLLECT_ALL((ref.name),
|
|
"KeymapNames", NULL), message);
|
|
itemsList.AddItem(item);
|
|
if (currentName == ref.name)
|
|
item->SetMarked(true);
|
|
|
|
if (usInternational == ref.name)
|
|
fDefaultKeymapItem = item;
|
|
}
|
|
itemsList.SortItems(compare_void_menu_items);
|
|
fKeymapsMenuField->Menu()->AddList(&itemsList, 0);
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
BootPromptWindow::_ActivateKeymap(const BMessage* message) const
|
|
{
|
|
entry_ref ref;
|
|
if (message == NULL || message->FindRef("ref", &ref) != B_OK)
|
|
return;
|
|
|
|
// Load and use the new keymap
|
|
Keymap keymap;
|
|
if (keymap.Load(ref) != B_OK) {
|
|
fprintf(stderr, "Failed to load new keymap file (%s).\n", ref.name);
|
|
return;
|
|
}
|
|
|
|
// Get entry_ref to the Key_map file in the user settings.
|
|
entry_ref currentRef;
|
|
if (_GetCurrentKeymapRef(currentRef) != B_OK) {
|
|
fprintf(stderr, "Failed to get ref to user keymap file.\n");
|
|
return;
|
|
}
|
|
|
|
if (keymap.Save(currentRef) != B_OK) {
|
|
fprintf(stderr, "Failed to save new keymap file (%s).\n", ref.name);
|
|
return;
|
|
}
|
|
|
|
keymap.Use();
|
|
}
|
|
|
|
|
|
status_t
|
|
BootPromptWindow::_GetCurrentKeymapRef(entry_ref& ref) const
|
|
{
|
|
BPath path;
|
|
if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK
|
|
|| path.Append("Key_map") != B_OK) {
|
|
return B_ERROR;
|
|
}
|
|
|
|
return get_ref_for_path(path.Path(), &ref);
|
|
}
|
|
|
|
|
|
BMenuItem*
|
|
BootPromptWindow::_KeymapItemForLanguage(BLanguage& language) const
|
|
{
|
|
BLanguage english("en");
|
|
BString name;
|
|
if (language.GetName(name, &english) != B_OK)
|
|
return fDefaultKeymapItem;
|
|
|
|
// Check special mappings first
|
|
for (size_t i = 0; i < kLanguageKeymapMappingsSize; i += 2) {
|
|
if (!strcmp(name, kLanguageKeymapMappings[i])) {
|
|
name = kLanguageKeymapMappings[i + 1];
|
|
break;
|
|
}
|
|
}
|
|
|
|
BMenu* menu = fKeymapsMenuField->Menu();
|
|
for (int32 i = 0; i < menu->CountItems(); i++) {
|
|
BMenuItem* item = menu->ItemAt(i);
|
|
BMessage* message = item->Message();
|
|
|
|
entry_ref ref;
|
|
if (message->FindRef("ref", &ref) == B_OK
|
|
&& name == ref.name)
|
|
return item;
|
|
}
|
|
|
|
return fDefaultKeymapItem;
|
|
}
|