diff --git a/src/plugin/Plugin.cpp b/src/plugin/Plugin.cpp index f3e4e95..3710e4b 100644 --- a/src/plugin/Plugin.cpp +++ b/src/plugin/Plugin.cpp @@ -172,7 +172,7 @@ void show_spell_check_menu_at_cursor() { context_menu_handler->update_word_under_cursor_data(); if (context_menu_handler->is_word_under_cursor_correct()) return; - MenuItem::append_to_menu(menu, context_menu_handler->get_suggestion_menu_items()); + MenuItem::append_to_menu(menu, context_menu_handler->select_word_and_get_suggestion_menu_items()); tagTPMPARAMS tpm_params; tpm_params.cbSize = sizeof(tagTPMPARAMS); diff --git a/src/plugin/Settings.cpp b/src/plugin/Settings.cpp index 507ddfa..f23aae2 100644 --- a/src/plugin/Settings.cpp +++ b/src/plugin/Settings.cpp @@ -291,4 +291,5 @@ void Settings::process(IniWorker &worker) { worker.process(L"Write_Debug_Log", data.write_debug_log, false); worker.process(L"FTP_use_passive_mode", data.ftp_use_passive_mode, true); worker.process(L"select_word_on_context_menu_click", data.select_word_on_context_menu_click, true); + worker.process(L"always_suggest_capitilized_word", data.always_suggest_capitalized_word, false); } diff --git a/src/plugin/Settings.h b/src/plugin/Settings.h index 9d5db03..5467aaf 100644 --- a/src/plugin/Settings.h +++ b/src/plugin/Settings.h @@ -200,6 +200,7 @@ class Settings { bool write_debug_log = false; LanguageNameStyle language_name_style = LanguageNameStyle::english; bool select_word_on_context_menu_click = false; + bool always_suggest_capitalized_word = false; // Derivatives: private: diff --git a/src/ui/ContextMenuHandler.cpp b/src/ui/ContextMenuHandler.cpp index 92afa3e..ced447d 100644 --- a/src/ui/ContextMenuHandler.cpp +++ b/src/ui/ContextMenuHandler.cpp @@ -104,18 +104,18 @@ void ContextMenuHandler::do_plugin_menu_inclusion(bool invalidate) { void ContextMenuHandler::process_ignore_all() { auto mut = m_speller_container.modify(); - mut->ignore_word(m_selected_word.str); + mut->ignore_word(m_last_selected_word.str); m_word_under_cursor_length = - static_cast(m_selected_word.str.length()); + static_cast(m_last_selected_word.str.length()); m_editor.set_cursor_pos(m_word_under_cursor_pos + m_word_under_cursor_length); } void ContextMenuHandler::process_add_to_dictionary() { auto mut = m_speller_container.modify(); - mut->add_to_dictionary(m_selected_word.str); + mut->add_to_dictionary(m_last_selected_word.str); m_word_under_cursor_length = - static_cast(m_selected_word.str.length()); + static_cast(m_last_selected_word.str.length()); m_editor.set_cursor_pos(m_word_under_cursor_pos + m_word_under_cursor_length); } @@ -243,7 +243,7 @@ void ContextMenuHandler::precalculate_menu() { m_settings.data.suggestions_mode == SuggestionMode::context_menu) { update_word_under_cursor_data(); if (!m_word_under_cursor_is_correct) { - suggestion_menu_items = get_suggestion_menu_items(); + suggestion_menu_items = select_word_and_get_suggestion_menu_items(); suggestion_menu_items.emplace_back(MenuItem::Separator{}); } } @@ -309,44 +309,57 @@ void ContextMenuHandler::init_suggestions_box( suggestion_button.display(true, false); } -std::vector -ContextMenuHandler::get_suggestion_menu_items() { - if (!m_speller_container.active_speller().is_working()) - return {}; // Word is already off-screen - +bool ContextMenuHandler::select_word_under_cursor() { auto pos = m_word_under_cursor_pos; ACTIVE_VIEW_BLOCK(m_editor); if (m_settings.data.select_word_on_context_menu_click) m_editor.set_selection(pos, pos + m_word_under_cursor_length); - std::vector suggestion_menu_items; - m_selected_word = m_editor.get_mapped_wstring_range(m_word_under_cursor_pos, m_word_under_cursor_pos + static_cast(m_word_under_cursor_length)); - SpellCheckerHelpers::apply_word_conversions(m_settings, m_selected_word.str); + m_last_selected_word = + m_editor.get_mapped_wstring_range(m_word_under_cursor_pos, m_word_under_cursor_pos + static_cast(m_word_under_cursor_length)); + SpellCheckerHelpers::apply_word_conversions(m_settings, m_last_selected_word.str); + return true; +} - m_last_suggestions = m_speller_container.active_speller().get_suggestions( - m_selected_word.str.c_str()); +std::vector ContextMenuHandler::select_word_and_get_suggestion_menu_items() { + if (!m_speller_container.active_speller().is_working()) + return {}; // Word is already off-screen - for (int i = 0; i < static_cast(m_last_suggestions.size()); i++) { - if (i >= m_settings.data.suggestion_count) - break; + select_word_under_cursor(); + std::vector suggestion_menu_items; + m_last_suggestions = m_speller_container.active_speller().get_suggestions( + m_last_selected_word.str.c_str()); + m_last_suggestions.resize(std::min(static_cast(m_last_suggestions.size()), m_settings.data.suggestion_count)); + int i = 0; + for (; i < static_cast(m_last_suggestions.size()); ++i) { auto item = m_last_suggestions[i].c_str(); suggestion_menu_items.emplace_back(item, static_cast(i + 1)); } + if (m_settings.data.always_suggest_capitalized_word && !m_last_selected_word.str.empty() && std::ranges::all_of(m_last_selected_word.str, &is_lower)) { + auto copy = m_last_selected_word.str; + copy.front() = make_upper(copy.front()); + if (std::ranges::find(m_last_suggestions, copy) == m_last_suggestions.end()) { + auto &last = m_last_suggestions.emplace_back(std::move(copy)); + ++i; + suggestion_menu_items.emplace_back(last.c_str(), static_cast(i + 1)); + } + } + if (!m_last_suggestions.empty()) { - MenuItem replace_all_item(wstring_printf(rc_str(IDS_REPLACE_ALL_PS).c_str(), m_selected_word.str.c_str()).c_str(), -1); + MenuItem replace_all_item(wstring_printf(rc_str(IDS_REPLACE_ALL_PS).c_str(), m_last_selected_word.str.c_str()).c_str(), -1); replace_all_item.children = suggestion_menu_items; suggestion_menu_items.emplace_back(MenuItem::Separator{}); std::for_each(replace_all_item.children.begin(), replace_all_item.children.end(), [](auto &item) { item.id += menu_id::replace_all_start; }); suggestion_menu_items.push_back(std::move(replace_all_item)); } - SpellCheckerHelpers::apply_word_conversions(m_settings, m_selected_word.str); + SpellCheckerHelpers::apply_word_conversions(m_settings, m_last_selected_word.str); auto menu_string = wstring_printf(rc_str(IDS_IGNORE_PS_FOR_CURRENT_SESSION).c_str(), - m_selected_word.str.c_str()); + m_last_selected_word.str.c_str()); suggestion_menu_items.emplace_back(menu_string.c_str(), menu_id::ignore_all); menu_string = - wstring_printf(rc_str(IDS_ADD_PS_TO_DICTIONARY).c_str(), m_selected_word.str.c_str());; + wstring_printf(rc_str(IDS_ADD_PS_TO_DICTIONARY).c_str(), m_last_selected_word.str.c_str());; suggestion_menu_items.emplace_back(menu_string.c_str(), menu_id::add_to_dictionary); diff --git a/src/ui/ContextMenuHandler.h b/src/ui/ContextMenuHandler.h index fa5f8f8..4f9aa5f 100644 --- a/src/ui/ContextMenuHandler.h +++ b/src/ui/ContextMenuHandler.h @@ -28,7 +28,7 @@ class ContextMenuHandler { const SpellerContainer &speller_container, EditorInterface &editor, const SpellChecker &spell_checker); - [[nodiscard]] std::vector get_suggestion_menu_items(); + [[nodiscard]] std::vector select_word_and_get_suggestion_menu_items(); void process_menu_result(WPARAM menu_id); void update_word_under_cursor_data(); void precalculate_menu(); @@ -36,6 +36,7 @@ class ContextMenuHandler { bool is_word_under_cursor_correct() const { return m_word_under_cursor_is_correct; } private: + bool select_word_under_cursor(); void do_plugin_menu_inclusion(bool invalidate = false); void process_ignore_all(); void process_add_to_dictionary(); @@ -48,7 +49,7 @@ class ContextMenuHandler { const Settings &m_settings; const SpellerContainer &m_speller_container; EditorInterface &m_editor; - MappedWstring m_selected_word; + MappedWstring m_last_selected_word; TextPosition m_word_under_cursor_length = 0; TextPosition m_word_under_cursor_pos = 0; std::vector m_last_suggestions; diff --git a/src/ui/SuggestionMenuButton.cpp b/src/ui/SuggestionMenuButton.cpp index ba29714..73f1ce4 100644 --- a/src/ui/SuggestionMenuButton.cpp +++ b/src/ui/SuggestionMenuButton.cpp @@ -177,7 +177,7 @@ INT_PTR SuggestionMenuButton::run_dlg_proc(UINT message, WPARAM w_param, ClientToScreen(_hSelf, &p); m_state_menu = true; HMENU popup_menu = CreatePopupMenu(); - MenuItem::append_to_menu(popup_menu, m_context_menu_handler.get_suggestion_menu_items()); + MenuItem::append_to_menu(popup_menu, m_context_menu_handler.select_word_and_get_suggestion_menu_items()); SetForegroundWindow(m_npp.get_editor_hwnd()); TrackPopupMenuEx(popup_menu, TPM_HORIZONTAL | TPM_RIGHTALIGN, p.x, p.y, _hSelf, &tpm_params);