Merge pull request #19492 from hrydgard/more-misc-fixes

RetroAchievements login: Implement password masking
This commit is contained in:
Henrik Rydgård 2024-09-26 12:37:10 +02:00 committed by GitHub
commit 9208d9d49a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
27 changed files with 171 additions and 148 deletions

View File

@ -78,6 +78,9 @@ void NativeShutdown();
void PostLoadConfig();
// Returns false on failure. Shouldn't really happen, though.
bool NativeSaveSecret(const char *nameOfSecret, const std::string &data);
bool NativeSaveSecret(std::string_view nameOfSecret, std::string_view data);
inline bool NativeClearSecret(std::string_view nameOfSecret) {
return NativeSaveSecret(nameOfSecret, "");
}
// On failure, returns an empty string. Good enough since any real secret is non-empty.
std::string NativeLoadSecret(const char *nameOfSecret);
std::string NativeLoadSecret(std::string_view nameOfSecret);

View File

@ -84,8 +84,8 @@ extern RequestManager g_requestManager;
// Wrappers for easy requests.
// NOTE: Semantics have changed - this no longer calls the callback on cancellation, instead you
// can specify a different callback for that.
inline void System_InputBoxGetString(RequesterToken token, std::string_view title, std::string_view defaultValue, RequestCallback callback, RequestFailedCallback failedCallback = nullptr) {
g_requestManager.MakeSystemRequest(SystemRequestType::INPUT_TEXT_MODAL, token, callback, failedCallback, title, defaultValue, 0);
inline void System_InputBoxGetString(RequesterToken token, std::string_view title, std::string_view defaultValue, bool passwordMasking, RequestCallback callback, RequestFailedCallback failedCallback = nullptr) {
g_requestManager.MakeSystemRequest(SystemRequestType::INPUT_TEXT_MODAL, token, callback, failedCallback, title, defaultValue, passwordMasking ? 1 : 0);
}
// This one will pop up a special image browser if available. You can also pick

View File

@ -528,7 +528,7 @@ EventReturn PopupTextInputChoice::HandleClick(EventParams &e) {
// Choose method depending on platform capabilities.
if (System_GetPropertyBool(SYSPROP_HAS_TEXT_INPUT_DIALOG)) {
System_InputBoxGetString(token_, text_, *value_ , [=](const std::string &enteredValue, int) {
System_InputBoxGetString(token_, text_, *value_, passwordMasking_, [=](const std::string &enteredValue, int) {
*value_ = StripSpaces(enteredValue);
EventParams params{};
OnChange.Trigger(params);
@ -537,6 +537,7 @@ EventReturn PopupTextInputChoice::HandleClick(EventParams &e) {
}
TextEditPopupScreen *popupScreen = new TextEditPopupScreen(value_, placeHolder_, ChopTitle(text_), maxLen_);
popupScreen->SetPasswordMasking(passwordMasking_);
if (System_GetPropertyBool(SYSPROP_KEYBOARD_IS_SOFT)) {
popupScreen->SetAlignTop(true);
}
@ -570,6 +571,7 @@ void TextEditPopupScreen::CreatePopupContents(UI::ViewGroup *parent) {
edit_ = new TextEdit(textEditValue_, Title(), placeholder_, new LinearLayoutParams(1.0f));
edit_->SetMaxLen(maxLen_);
edit_->SetTextColor(dc.theme->popupStyle.fgColor);
edit_->SetPasswordMasking(passwordMasking_);
lin->Add(edit_);
UI::SetFocusedView(edit_);
@ -628,7 +630,7 @@ void AbstractChoiceWithValueDisplay::Draw(UIContext &dc) {
std::string valueText = ValueText();
if (passwordDisplay_) {
if (passwordMasking_) {
// Replace all characters with stars.
memset(&valueText[0], '*', valueText.size());
}

View File

@ -150,6 +150,10 @@ public:
const char *tag() const override { return "TextEditPopup"; }
void SetPasswordMasking(bool masking) {
passwordMasking_ = masking;
}
Event OnChange;
private:
@ -159,6 +163,7 @@ private:
std::string textEditValue_;
std::string placeholder_;
int maxLen_;
bool passwordMasking_ = false;
};
struct ContextMenuItem {

View File

@ -1142,18 +1142,25 @@ void TextEdit::Draw(UIContext &dc) {
Bounds textBounds = bounds_;
textBounds.x = textX - scrollPos_;
std::string textToDisplay = text_;
if (passwordMasking_) {
for (int i = 0; i < textToDisplay.size(); i++) {
textToDisplay[i] = '*';
}
}
if (text_.empty()) {
if (placeholderText_.size()) {
uint32_t c = textColor & 0x50FFFFFF;
dc.DrawTextRect(placeholderText_, bounds_, c, ALIGN_CENTER);
}
} else {
dc.DrawTextRect(text_, textBounds, textColor, ALIGN_VCENTER | ALIGN_LEFT | align_);
dc.DrawTextRect(textToDisplay, textBounds, textColor, ALIGN_VCENTER | ALIGN_LEFT | align_);
}
if (HasFocus()) {
// Hack to find the caret position. Might want to find a better way...
dc.MeasureText(dc.theme->uiFont, 1.0f, 1.0f, text_.substr(0, caret_), &w, &h, ALIGN_VCENTER | ALIGN_LEFT | align_);
dc.MeasureText(dc.theme->uiFont, 1.0f, 1.0f, textToDisplay.substr(0, caret_), &w, &h, ALIGN_VCENTER | ALIGN_LEFT | align_);
float caretX = w - scrollPos_;
if (caretX > bounds_.w) {
scrollPos_ += caretX - bounds_.w;

View File

@ -825,14 +825,14 @@ public:
void GetContentDimensionsBySpec(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert, float &w, float &h) const override;
void SetPasswordDisplay() {
passwordDisplay_ = true;
passwordMasking_ = true;
}
protected:
virtual std::string ValueText() const = 0;
float CalculateValueScale(const UIContext &dc, std::string_view valueText, float availWidth) const;
bool passwordDisplay_ = false;
bool passwordMasking_ = false;
};
class ChoiceWithCallbackValueDisplay : public AbstractChoiceWithValueDisplay {
@ -1026,6 +1026,9 @@ public:
const std::string &GetText() const { return text_; }
void SetMaxLen(size_t maxLen) { maxLen_ = maxLen; }
void SetTextAlign(int align) { align_ = align; } // Only really useful for setting FLAG_DYNAMIC_ASCII
void SetPasswordMasking(bool masking) {
passwordMasking_ = masking;
}
void FocusChanged(int focusFlags) override;
void GetContentDimensions(const UIContext &dc, float &w, float &h) const override;
@ -1050,6 +1053,7 @@ private:
int scrollPos_ = 0;
size_t maxLen_;
bool ctrlDown_ = false; // TODO: Make some global mechanism for this.
bool passwordMasking_ = false;
int align_ = 0;
// TODO: Selections
};

View File

@ -897,7 +897,7 @@ int PSPOskDialog::NativeKeyboard() {
defaultText.assign(u"VALUE");
// There's already ConvertUCS2ToUTF8 in this file. Should we use that instead of the global ones?
System_InputBoxGetString(NON_EPHEMERAL_TOKEN, ::ConvertUCS2ToUTF8(titleText), ::ConvertUCS2ToUTF8(defaultText),
System_InputBoxGetString(NON_EPHEMERAL_TOKEN, ::ConvertUCS2ToUTF8(titleText), ::ConvertUCS2ToUTF8(defaultText), false,
[&](const std::string &value, int) {
// Success callback
std::lock_guard<std::mutex> guard(nativeMutex_);

View File

@ -503,8 +503,19 @@ static void login_token_callback(int result, const char *error_message, rc_clien
auto ac = GetI18NCategory(I18NCat::ACHIEVEMENTS);
g_OSD.Show(OSDType::MESSAGE_WARNING, ac->T("Failed logging in to RetroAchievements"), "", g_RAImageID);
}
// Clear the token.
if (result == RC_INVALID_CREDENTIALS || result == RC_EXPIRED_TOKEN) {
g_Config.sAchievementsUserName.clear();
NativeClearSecret(RA_TOKEN_SECRET_NAME);
g_loginResult = RC_OK;
} else {
g_loginResult = result;
}
OnAchievementsLoginStateChange();
break;
g_isLoggingIn = false;
return;
}
}
g_loginResult = result;
@ -718,7 +729,7 @@ void Logout() {
rc_client_logout(g_rcClient);
// remove from config
g_Config.sAchievementsUserName.clear();
NativeSaveSecret(RA_TOKEN_SECRET_NAME, "");
NativeClearSecret(RA_TOKEN_SECRET_NAME);
g_Config.Save("Achievements logout");
g_activeChallenges.clear();
g_loginResult = RC_OK; // Allow trying again

View File

@ -234,7 +234,8 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string
g_QuitRequested = true;
return true;
#if PPSSPP_PLATFORM(SWITCH)
case SystemRequestType::INPUT_TEXT_MODAL: {
case SystemRequestType::INPUT_TEXT_MODAL:
{
// swkbd only works on "real" titles
if (__nx_applet_type != AppletType_Application && __nx_applet_type != AppletType_SystemApplication) {
g_requestManager.PostSystemFailure(requestId);

View File

@ -97,7 +97,7 @@ UI::EventReturn ChatMenu::OnSubmit(UI::EventParams &e) {
sendChat(chat);
#elif PPSSPP_PLATFORM(ANDROID) || PPSSPP_PLATFORM(SWITCH) || PPSSPP_PLATFORM(IOS)
auto n = GetI18NCategory(I18NCat::NETWORKING);
System_InputBoxGetString(token_, n->T("Chat"), "", [](const std::string &value, int) {
System_InputBoxGetString(token_, n->T("Chat"), "", false, [](const std::string &value, int) {
sendChat(value);
});
#endif
@ -180,7 +180,7 @@ void ChatMenu::Update() {
// Could remove the fullscreen check here, it works now.
auto n = GetI18NCategory(I18NCat::NETWORKING);
if (promptInput_ && g_Config.bBypassOSKWithKeyboard && !g_Config.UseFullScreen()) {
System_InputBoxGetString(token_, n->T("Chat"), n->T("Chat Here"), [](const std::string &value, int) {
System_InputBoxGetString(token_, n->T("Chat"), n->T("Chat Here"), false, [](const std::string &value, int) {
sendChat(value);
});
promptInput_ = false;

View File

@ -1648,7 +1648,7 @@ UI::EventReturn GameSettingsScreen::OnAudioDevice(UI::EventParams &e) {
UI::EventReturn GameSettingsScreen::OnChangeQuickChat0(UI::EventParams &e) {
#if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI) || PPSSPP_PLATFORM(ANDROID) || PPSSPP_PLATFORM(SWITCH)
auto n = GetI18NCategory(I18NCat::NETWORKING);
System_InputBoxGetString(GetRequesterToken(), n->T("Enter Quick Chat 1"), g_Config.sQuickChat0, [](const std::string &value, int) {
System_InputBoxGetString(GetRequesterToken(), n->T("Enter Quick Chat 1"), g_Config.sQuickChat0, false, [](const std::string &value, int) {
g_Config.sQuickChat0 = value;
});
#endif
@ -1658,7 +1658,7 @@ UI::EventReturn GameSettingsScreen::OnChangeQuickChat0(UI::EventParams &e) {
UI::EventReturn GameSettingsScreen::OnChangeQuickChat1(UI::EventParams &e) {
#if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI) || PPSSPP_PLATFORM(ANDROID) || PPSSPP_PLATFORM(SWITCH)
auto n = GetI18NCategory(I18NCat::NETWORKING);
System_InputBoxGetString(GetRequesterToken(), n->T("Enter Quick Chat 2"), g_Config.sQuickChat1, [](const std::string &value, int) {
System_InputBoxGetString(GetRequesterToken(), n->T("Enter Quick Chat 2"), g_Config.sQuickChat1, false, [](const std::string &value, int) {
g_Config.sQuickChat1 = value;
});
#endif
@ -1668,7 +1668,7 @@ UI::EventReturn GameSettingsScreen::OnChangeQuickChat1(UI::EventParams &e) {
UI::EventReturn GameSettingsScreen::OnChangeQuickChat2(UI::EventParams &e) {
#if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI) || PPSSPP_PLATFORM(ANDROID) || PPSSPP_PLATFORM(SWITCH)
auto n = GetI18NCategory(I18NCat::NETWORKING);
System_InputBoxGetString(GetRequesterToken(), n->T("Enter Quick Chat 3"), g_Config.sQuickChat2, [](const std::string &value, int) {
System_InputBoxGetString(GetRequesterToken(), n->T("Enter Quick Chat 3"), g_Config.sQuickChat2, false, [](const std::string &value, int) {
g_Config.sQuickChat2 = value;
});
#endif
@ -1678,7 +1678,7 @@ UI::EventReturn GameSettingsScreen::OnChangeQuickChat2(UI::EventParams &e) {
UI::EventReturn GameSettingsScreen::OnChangeQuickChat3(UI::EventParams &e) {
#if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI) || PPSSPP_PLATFORM(ANDROID) || PPSSPP_PLATFORM(SWITCH)
auto n = GetI18NCategory(I18NCat::NETWORKING);
System_InputBoxGetString(GetRequesterToken(), n->T("Enter Quick Chat 4"), g_Config.sQuickChat3, [](const std::string &value, int) {
System_InputBoxGetString(GetRequesterToken(), n->T("Enter Quick Chat 4"), g_Config.sQuickChat3, false, [](const std::string &value, int) {
g_Config.sQuickChat3 = value;
});
#endif
@ -1688,7 +1688,7 @@ UI::EventReturn GameSettingsScreen::OnChangeQuickChat3(UI::EventParams &e) {
UI::EventReturn GameSettingsScreen::OnChangeQuickChat4(UI::EventParams &e) {
#if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI) || PPSSPP_PLATFORM(ANDROID) || PPSSPP_PLATFORM(SWITCH)
auto n = GetI18NCategory(I18NCat::NETWORKING);
System_InputBoxGetString(GetRequesterToken(), n->T("Enter Quick Chat 5"), g_Config.sQuickChat4, [](const std::string &value, int) {
System_InputBoxGetString(GetRequesterToken(), n->T("Enter Quick Chat 5"), g_Config.sQuickChat4, false, [](const std::string &value, int) {
g_Config.sQuickChat4 = value;
});
#endif
@ -1698,7 +1698,7 @@ UI::EventReturn GameSettingsScreen::OnChangeQuickChat4(UI::EventParams &e) {
UI::EventReturn GameSettingsScreen::OnChangeNickname(UI::EventParams &e) {
#if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI) || PPSSPP_PLATFORM(ANDROID) || PPSSPP_PLATFORM(SWITCH)
auto n = GetI18NCategory(I18NCat::NETWORKING);
System_InputBoxGetString(GetRequesterToken(), n->T("Enter a new PSP nickname"), g_Config.sNickName, [](const std::string &value, int) {
System_InputBoxGetString(GetRequesterToken(), n->T("Enter a new PSP nickname"), g_Config.sNickName, false, [](const std::string &value, int) {
g_Config.sNickName = StripSpaces(value);
});
#endif
@ -2325,7 +2325,7 @@ UI::EventReturn HostnameSelectScreen::OnDeleteAllClick(UI::EventParams &e) {
UI::EventReturn HostnameSelectScreen::OnEditClick(UI::EventParams& e) {
auto n = GetI18NCategory(I18NCat::NETWORKING);
System_InputBoxGetString(GetRequesterToken(), n->T("proAdhocServer Address:"), addrView_->GetText(), [this](const std::string& value, int) {
System_InputBoxGetString(GetRequesterToken(), n->T("proAdhocServer Address:"), addrView_->GetText(), false, [this](const std::string& value, int) {
addrView_->SetText(value);
});
return UI::EVENT_DONE;

View File

@ -237,7 +237,7 @@ void InstallZipScreen::update() {
if (existingSaveView_) {
std::shared_ptr<GameInfo> ginfo = g_gameInfoCache->GetInfo(screenManager()->getDrawContext(), savedataToOverwrite_, GameInfoFlags::FILE_TYPE | GameInfoFlags::PARAM_SFO | GameInfoFlags::ICON | GameInfoFlags::SIZE);
existingSaveView_->Update(ginfo.get());
existingSaveView_->UpdateGame(ginfo.get());
}
UIDialogScreenWithBackground::update();
}

View File

@ -344,7 +344,7 @@ void GameButton::Draw(UIContext &dc) {
dc.PushScissor(bounds_);
const std::string currentTitle = ginfo->GetTitle();
if (!currentTitle.empty()) {
title_ = ReplaceAll(title_, "\n", " ");
title_ = ReplaceAll(currentTitle, "\n", " ");
}
dc.MeasureText(dc.GetFontStyle(), 1.0f, 1.0f, title_, &tw, &th, 0);
@ -798,7 +798,7 @@ void GameBrowser::Refresh() {
if (System_GetPropertyInt(SYSPROP_DEVICE_TYPE) == DEVICE_TYPE_TV) {
topBar->Add(new Choice(mm->T("Enter Path"), new LayoutParams(WRAP_CONTENT, 64.0f)))->OnClick.Add([=](UI::EventParams &) {
auto mm = GetI18NCategory(I18NCat::MAINMENU);
System_InputBoxGetString(token_, mm->T("Enter Path"), path_.GetPath().ToString(), [=](const char *responseString, int responseValue) {
System_InputBoxGetString(token_, mm->T("Enter Path"), path_.GetPath().ToString(), false, [=](const char *responseString, int responseValue) {
this->SetPath(Path(responseString));
});
return UI::EVENT_DONE;
@ -1358,7 +1358,7 @@ bool MainScreen::key(const KeyInput &touch) {
searchKeyModifier_ = true;
if (touch.keyCode == NKCODE_F && searchKeyModifier_ && System_GetPropertyBool(SYSPROP_HAS_TEXT_INPUT_DIALOG)) {
auto se = GetI18NCategory(I18NCat::SEARCH);
System_InputBoxGetString(GetRequesterToken(), se->T("Search term"), searchFilter_, [&](const std::string &value, int) {
System_InputBoxGetString(GetRequesterToken(), se->T("Search term"), searchFilter_, false, [&](const std::string &value, int) {
searchFilter_ = StripSpaces(value);
searchChanged_ = true;
});

View File

@ -305,7 +305,7 @@ UI::EventReturn MemStickScreen::SetFolderManually(UI::EventParams &params) {
// The old way, from before scoped storage. Write in the full path.
#if PPSSPP_PLATFORM(ANDROID) || PPSSPP_PLATFORM(SWITCH)
auto sy = GetI18NCategory(I18NCat::SYSTEM);
System_InputBoxGetString(GetRequesterToken(), sy->T("Memory Stick Folder"), g_Config.memStickDirectory.ToString(), [&](const std::string &value, int) {
System_InputBoxGetString(GetRequesterToken(), sy->T("Memory Stick Folder"), g_Config.memStickDirectory.ToString(), false, [&](const std::string &value, int) {
auto sy = GetI18NCategory(I18NCat::SYSTEM);
auto di = GetI18NCategory(I18NCat::DIALOG);

View File

@ -1536,22 +1536,24 @@ void NativeShutdown() {
// In the future, we might make this more sophisticated, such as storing in the app private directory on Android.
// Right now we just store secrets in separate files next to ppsspp.ini. The important thing is keeping them out of it
// since we often ask people to post or send the ini for debugging.
static Path GetSecretPath(const char *nameOfSecret) {
static Path GetSecretPath(std::string_view nameOfSecret) {
return GetSysDirectory(DIRECTORY_SYSTEM) / ("ppsspp_" + std::string(nameOfSecret) + ".dat");
}
// name should be simple alphanumerics to avoid problems on Windows.
bool NativeSaveSecret(const char *nameOfSecret, const std::string &data) {
bool NativeSaveSecret(std::string_view nameOfSecret, std::string_view data) {
Path path = GetSecretPath(nameOfSecret);
if (!File::WriteDataToFile(false, data.data(), data.size(), path)) {
WARN_LOG(Log::System, "Failed to write secret '%s' to path '%s'", nameOfSecret, path.c_str());
if (data.empty() && File::Exists(path)) {
return File::Delete(path);
} else if (!File::WriteDataToFile(false, data.data(), data.size(), path)) {
WARN_LOG(Log::System, "Failed to write secret '%.*s' to path '%s'", (int)nameOfSecret.size(), nameOfSecret.data(), path.c_str());
return false;
}
return true;
}
// On failure, returns an empty string. Good enough since any real secret is non-empty.
std::string NativeLoadSecret(const char *nameOfSecret) {
std::string NativeLoadSecret(std::string_view nameOfSecret) {
Path path = GetSecretPath(nameOfSecret);
std::string data;
if (!File::ReadBinaryFileToString(path, &data)) {

View File

@ -92,7 +92,7 @@ SavedataView::SavedataView(UIContext &dc, const Path &savePath, IdentifiedFileTy
}
}
void SavedataView::Update(GameInfo *ginfo) {
void SavedataView::UpdateGame(GameInfo *ginfo) {
if (!ginfo->Ready(GameInfoFlags::PARAM_SFO | GameInfoFlags::SIZE)) {
return;
}
@ -123,7 +123,7 @@ SavedataView::SavedataView(UIContext &dc, GameInfo *ginfo, IdentifiedFileType ty
showIcon,
layoutParams) {
if (ginfo) {
Update(ginfo);
UpdateGame(ginfo);
}
}
@ -140,7 +140,7 @@ public:
return;
}
if (savedataView_) {
savedataView_->Update(ginfo.get());
savedataView_->UpdateGame(ginfo.get());
}
}
@ -670,7 +670,7 @@ UI::EventReturn SavedataScreen::OnSortClick(UI::EventParams &e) {
UI::EventReturn SavedataScreen::OnSearch(UI::EventParams &e) {
if (System_GetPropertyBool(SYSPROP_HAS_TEXT_INPUT_DIALOG)) {
auto di = GetI18NCategory(I18NCat::DIALOG);
System_InputBoxGetString(GetRequesterToken(), di->T("Filter"), searchFilter_, [](const std::string &value, int ivalue) {
System_InputBoxGetString(GetRequesterToken(), di->T("Filter"), searchFilter_, false, [](const std::string &value, int ivalue) {
System_PostUIMessage(UIMessage::SAVEDATA_SEARCH, value);
});
}

View File

@ -152,7 +152,7 @@ public:
SavedataView(UIContext &dc, GameInfo *ginfo, IdentifiedFileType type, bool showIcon, UI::LayoutParams *layoutParams = nullptr);
SavedataView(UIContext &dc, const Path &savePath, IdentifiedFileType type, std::string_view title, std::string_view savedataTitle, std::string_view savedataDetail, std::string_view fileSize, std::string_view mtime, bool showIcon, UI::LayoutParams *layoutParams = nullptr);
void Update(GameInfo *ginfo);
void UpdateGame(GameInfo *ginfo);
private:
UI::TextView *savedataTitle_ = nullptr;
UI::TextView *detail_ = nullptr;

View File

@ -280,21 +280,22 @@ std::string trimString(std::string input)
void CtrlDisAsmView::assembleOpcode(u32 address, const std::string &defaultText)
{
auto memLock = Memory::Lock();
if (Core_IsStepping() == false) {
if (!Core_IsStepping()) {
MessageBox(wnd,L"Cannot change code while the core is running!",L"Error",MB_OK);
return;
}
std::string op;
bool result = InputBox_GetString(MainWindow::GetHInstance(),wnd,L"Assemble opcode",defaultText, op, false);
if (!result)
bool result = InputBox_GetString(MainWindow::GetHInstance(), wnd, L"Assemble opcode", defaultText, op, InputBoxFlags::Default);
if (!result) {
return;
}
// check if it changes registers first
auto seperator = op.find('=');
if (seperator != std::string::npos)
auto separator = op.find('=');
if (separator != std::string::npos)
{
std::string registerName = trimString(op.substr(0,seperator));
std::string expression = trimString(op.substr(seperator+1));
std::string registerName = trimString(op.substr(0,separator));
std::string expression = trimString(op.substr(separator+1));
u32 value;
if (parseExpression(expression.c_str(),debugger,value) == true)

View File

@ -18,7 +18,7 @@ void displayExpressionError(HWND hwnd)
bool executeExpressionWindow(HWND hwnd, DebugInterface* cpu, u32& dest)
{
std::string expression;
if (InputBox_GetString(GetModuleHandle(NULL), hwnd, L"Expression", "",expression) == false)
if (InputBox_GetString(GetModuleHandle(NULL), hwnd, L"Expression", "", expression) == false)
{
return false;
}
@ -30,4 +30,4 @@ bool executeExpressionWindow(HWND hwnd, DebugInterface* cpu, u32& dest)
}
return true;
}
}

View File

@ -397,7 +397,7 @@ void CtrlDisplayListView::onMouseUp(WPARAM wParam, LPARAM lParam, int button)
case ID_GEDBG_GOTOADDR:
{
std::string expression = StringFromFormat("%08x", curAddress);
if (!InputBox_GetString(GetModuleHandle(NULL), wnd, L"Address", expression, expression, true)) {
if (!InputBox_GetString(GetModuleHandle(NULL), wnd, L"Address", expression, expression, InputBoxFlags::Selected)) {
break;
}
uint32_t newAddress = curAddress;

View File

@ -348,6 +348,7 @@ void CGEDebugger::UpdatePrimPreview(u32 op, int which) {
u16 minIndex = 0;
u16 maxIndex = count - 1;
if (!indices.empty()) {
_dbg_assert_(count <= indices.size());
minIndex = 0xFFFF;
maxIndex = 0;
for (int i = 0; i < count; ++i) {

View File

@ -6,31 +6,45 @@
#include "Windows/W32Util/Misc.h"
#include "Common/Data/Encoding/Utf8.h"
static std::wstring textBoxContents;
static std::wstring passwordContents;
static std::wstring out;
static std::wstring windowTitle;
static bool defaultSelected;
static std::string g_userName;
static std::string g_passWord;
struct DialogBoxParams {
std::wstring textBoxContents;
std::wstring passwordContents;
std::wstring out;
std::wstring windowTitle;
bool defaultSelected;
bool passwordMasking;
std::string userName;
std::string passWord;
};
static DialogBoxParams g_params;
static INT_PTR CALLBACK InputBoxFunc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message) {
case WM_INITDIALOG:
SetWindowText(GetDlgItem(hDlg, IDC_INPUTBOX), textBoxContents.c_str());
SetWindowText(hDlg, windowTitle.c_str());
if (defaultSelected == false)
PostMessage(GetDlgItem(hDlg,IDC_INPUTBOX),EM_SETSEL,-1,-1);
{
HWND hwndTextBox = GetDlgItem(hDlg, IDC_INPUTBOX);
SetWindowText(hwndTextBox, g_params.textBoxContents.c_str());
SetWindowText(hDlg, g_params.windowTitle.c_str());
if (!g_params.defaultSelected) {
PostMessage(hwndTextBox, EM_SETSEL, -1, -1);
}
if (g_params.passwordMasking) {
LONG_PTR style = GetWindowLongPtr(hwndTextBox, GWL_STYLE);
SetWindowLongPtr(hwndTextBox, GWL_STYLE, style | ES_PASSWORD);
SendMessage(hwndTextBox, EM_SETPASSWORDCHAR, (WPARAM)'*', 0);
}
W32Util::CenterWindow(hDlg);
return TRUE;
}
case WM_COMMAND:
switch (wParam) {
case IDOK:
{
wchar_t temp[512];
GetWindowText(GetDlgItem(hDlg, IDC_INPUTBOX), temp, ARRAY_SIZE(temp) - 1);
out = temp;
GetWindowText(GetDlgItem(hDlg, IDC_INPUTBOX), temp, ARRAY_SIZE(temp));
g_params.out = temp;
EndDialog(hDlg, IDOK);
return TRUE;
}
@ -45,97 +59,55 @@ static INT_PTR CALLBACK InputBoxFunc(HWND hDlg, UINT message, WPARAM wParam, LPA
}
}
bool InputBox_GetString(HINSTANCE hInst, HWND hParent, const wchar_t *title, const std::string &defaultValue, std::string &outvalue, bool selected)
{
defaultSelected = selected;
if (defaultValue.size() < 255)
textBoxContents = ConvertUTF8ToWString(defaultValue);
else
textBoxContents.clear();
if (title != NULL)
windowTitle = title;
else
windowTitle.clear();
if (IDOK == DialogBox(hInst, (LPCWSTR)IDD_INPUTBOX, hParent, InputBoxFunc)) {
outvalue = ConvertWStringToUTF8(out);
return true;
}
else
return false;
}
bool InputBox_GetString(HINSTANCE hInst, HWND hParent, const wchar_t *title, const std::string &defaultValue, std::string &outvalue)
{
bool InputBox_GetString(HINSTANCE hInst, HWND hParent, const wchar_t *title, const std::string &defaultValue, std::string &outvalue, InputBoxFlags flags) {
const wchar_t *defaultTitle = L"Input value";
defaultSelected = true;
textBoxContents = ConvertUTF8ToWString(defaultValue);
g_params.defaultSelected = flags & InputBoxFlags::Selected;
g_params.passwordMasking = flags & InputBoxFlags::PasswordMasking;
if (defaultValue.size() < 255) {
g_params.textBoxContents = ConvertUTF8ToWString(defaultValue);
} else {
g_params.textBoxContents.clear();
}
if (title && wcslen(title) <= 0)
windowTitle = defaultTitle;
else if (title && wcslen(title) < 255)
windowTitle = title;
else
windowTitle = defaultTitle;
if (title && wcslen(title) <= 0) {
g_params.windowTitle = defaultTitle;
} else if (title && wcslen(title) < 255) {
g_params.windowTitle = title;
} else {
g_params.windowTitle = defaultTitle;
}
if (IDOK == DialogBox(hInst, (LPCWSTR)IDD_INPUTBOX, hParent, InputBoxFunc)) {
outvalue = ConvertWStringToUTF8(out);
outvalue = ConvertWStringToUTF8(g_params.out);
return true;
}
else
} else {
return false;
}
}
bool InputBox_GetWString(HINSTANCE hInst, HWND hParent, const wchar_t *title, const std::wstring &defaultValue, std::wstring &outvalue)
{
const wchar_t *defaultTitle = L"Input value";
defaultSelected = true;
textBoxContents = defaultValue;
if (title && wcslen(title) <= 0)
windowTitle = defaultTitle;
else if (title && wcslen(title) < 255)
windowTitle = title;
else
windowTitle = defaultTitle;
if (IDOK == DialogBox(hInst, (LPCWSTR)IDD_INPUTBOX, hParent, InputBoxFunc)) {
outvalue = out;
return true;
}
else
return false;
}
bool InputBox_GetHex(HINSTANCE hInst, HWND hParent, const wchar_t* title, u32 defaultvalue, u32& outvalue)
{
bool InputBox_GetHex(HINSTANCE hInst, HWND hParent, const wchar_t* title, u32 defaultvalue, u32 &outvalue) {
const wchar_t *defaultTitle = L"Input value";
wchar_t temp[256];
wsprintf(temp, L"%08x", defaultvalue);
textBoxContents = temp;
g_params.textBoxContents = temp;
if (title && wcslen(title) <= 0)
windowTitle = defaultTitle;
g_params.windowTitle = defaultTitle;
else if (title && wcslen(title) < 255)
windowTitle = title;
g_params.windowTitle = title;
else
windowTitle = defaultTitle;
g_params.windowTitle = defaultTitle;
INT_PTR value = DialogBox(hInst, (LPCWSTR)IDD_INPUTBOX, hParent, InputBoxFunc);
if (value == IDOK)
{
if (swscanf(out.c_str(), L"0x%08x", &outvalue) == 1)
if (value == IDOK) {
if (swscanf(g_params.out.c_str(), L"0x%08x", &outvalue) == 1)
return true;
if (swscanf(out.c_str(), L"%08x", &outvalue) == 1)
if (swscanf(g_params.out.c_str(), L"%08x", &outvalue) == 1)
return true;
return false;
}
else
{
} else {
outvalue = 0;
return false;
}
@ -147,7 +119,7 @@ static INT_PTR CALLBACK UserPasswordBoxFunc(HWND hDlg, UINT message, WPARAM wPar
case WM_INITDIALOG:
SetWindowText(GetDlgItem(hDlg, IDC_INPUTBOX), L"");
SetWindowText(GetDlgItem(hDlg, IDC_PASSWORDBOX), L"");
SetWindowText(hDlg, windowTitle.c_str());
SetWindowText(hDlg, g_params.windowTitle.c_str());
PostMessage(GetDlgItem(hDlg, IDC_INPUTBOX), EM_SETSEL, -1, -1);
PostMessage(GetDlgItem(hDlg, IDC_PASSWORDBOX), EM_SETSEL, -1, -1);
W32Util::CenterWindow(hDlg);
@ -158,10 +130,10 @@ static INT_PTR CALLBACK UserPasswordBoxFunc(HWND hDlg, UINT message, WPARAM wPar
case IDOK:
{
wchar_t temp[256];
GetWindowText(GetDlgItem(hDlg, IDC_INPUTBOX), temp, 255);
g_userName = ConvertWStringToUTF8(temp);
GetWindowText(GetDlgItem(hDlg, IDC_PASSWORDBOX), temp, 255);
g_passWord = ConvertWStringToUTF8(temp);
GetWindowText(GetDlgItem(hDlg, IDC_INPUTBOX), temp, sizeof(temp));
g_params.userName = ConvertWStringToUTF8(temp);
GetWindowText(GetDlgItem(hDlg, IDC_PASSWORDBOX), temp, sizeof(temp));
g_params.passWord = ConvertWStringToUTF8(temp);
EndDialog(hDlg, IDOK);
return TRUE;
}
@ -177,12 +149,12 @@ static INT_PTR CALLBACK UserPasswordBoxFunc(HWND hDlg, UINT message, WPARAM wPar
}
bool UserPasswordBox_GetStrings(HINSTANCE hInst, HWND hParent, const wchar_t *title, std::string *username, std::string *password) {
windowTitle = title;
g_params.windowTitle = title;
INT_PTR value = DialogBox(hInst, (LPCWSTR)IDD_USERPASSWORDBOX, hParent, UserPasswordBoxFunc);
if (value == IDOK) {
*username = g_userName;
*password = g_passWord;
*username = g_params.userName;
*password = g_params.passWord;
return true;
} else {
return false;

View File

@ -2,11 +2,17 @@
#include <string>
#include "Common/CommonWindows.h"
#include "Common/Common.h"
enum class InputBoxFlags {
Default = 0,
Selected = 1,
PasswordMasking = 2,
};
ENUM_CLASS_BITOPS(InputBoxFlags);
// All I/O is in UTF-8
bool InputBox_GetString(HINSTANCE hInst, HWND hParent, const wchar_t *title, const std::string &defaultvalue, std::string &outvalue, bool selected);
bool InputBox_GetString(HINSTANCE hInst, HWND hParent, const wchar_t *title, const std::string &defaultvalue, std::string &outvalue);
bool InputBox_GetWString(HINSTANCE hInst, HWND hParent, const wchar_t *title, const std::wstring &defaultvalue, std::wstring &outvalue);
bool InputBox_GetString(HINSTANCE hInst, HWND hParent, const wchar_t *title, const std::string &defaultvalue, std::string &outvalue, InputBoxFlags flags = InputBoxFlags::Default);
bool InputBox_GetHex(HINSTANCE hInst, HWND hParent, const wchar_t *title, u32 defaultvalue, u32 &outvalue);
bool UserPasswordBox_GetStrings(HINSTANCE hInst, HWND hParent, const wchar_t *title, std::string *username, std::string *password);

View File

@ -540,7 +540,14 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string
case SystemRequestType::INPUT_TEXT_MODAL:
std::thread([=] {
std::string out;
if (InputBox_GetString(MainWindow::GetHInstance(), MainWindow::GetHWND(), ConvertUTF8ToWString(param1).c_str(), param2, out)) {
InputBoxFlags flags{};
if (param3) {
flags |= InputBoxFlags::PasswordMasking;
}
if (!param2.empty()) {
flags |= InputBoxFlags::Selected;
}
if (InputBox_GetString(MainWindow::GetHInstance(), MainWindow::GetHWND(), ConvertUTF8ToWString(param1).c_str(), param2, out, flags)) {
g_requestManager.PostSystemSuccess(requestId, out.c_str());
} else {
g_requestManager.PostSystemFailure(requestId);

View File

@ -142,8 +142,8 @@ void System_AudioClear() {}
void System_AudioPushSamples(const s32 *audio, int numSamples) {}
// TODO: To avoid having to define these here, these should probably be turned into system "requests".
bool NativeSaveSecret(const char *nameOfSecret, const std::string &data) { return false; }
std::string NativeLoadSecret(const char *nameOfSecret) {
bool NativeSaveSecret(std::string_view nameOfSecret, std::string_view data) { return false; }
std::string NativeLoadSecret(std::string_view nameOfSecret) {
return "";
}

View File

@ -1962,7 +1962,7 @@ bool System_AudioRecordingState() { return false; }
#endif
// TODO: To avoid having to define these here, these should probably be turned into system "requests".
bool NativeSaveSecret(const char *nameOfSecret, const std::string &data) { return false; }
std::string NativeLoadSecret(const char *nameOfSecret) {
bool NativeSaveSecret(std::string_view nameOfSecret, std::string_view data) { return false; }
std::string NativeLoadSecret(std::string_view nameOfSecret) {
return "";
}

View File

@ -108,8 +108,9 @@ void System_AudioClear() {}
void System_AudioPushSamples(const s32 *audio, int numSamples) {}
// TODO: To avoid having to define these here, these should probably be turned into system "requests".
bool NativeSaveSecret(const char *nameOfSecret, const std::string &data) { return false; }
std::string NativeLoadSecret(const char *nameOfSecret) {
// To clear the secret entirely, just save an empty string.
bool NativeSaveSecret(std::string_view nameOfSecret, std::string_view data) { return false; }
std::string NativeLoadSecret(std::string_view nameOfSecret) {
return "";
}