From 23d460fe0713a9d2f45fb8b42bf0f1eab30d036c Mon Sep 17 00:00:00 2001
From: Blake-Madden <66873089+Blake-Madden@users.noreply.github.com>
Date: Wed, 27 Nov 2024 09:48:34 -0500
Subject: [PATCH] Add option to encode extended ASCII characters from the
editor
---
docs/manual/_quarto.yml | 1 +
docs/manual/_quarto.yml.in | 1 +
docs/manual/gui/editing.qmd | 41 ++++++++++
docs/manual/gui/reviewing-output.qmd | 12 +--
gui/images/unicode-encoded.svg | 117 +++++++++++++++++++++++++++
src/analyze.cpp | 1 -
src/gui/i18napp.cpp | 1 +
src/gui/i18nframe.cpp | 60 +++++++++++++-
src/gui/i18nframe.h | 1 +
9 files changed, 220 insertions(+), 15 deletions(-)
create mode 100644 docs/manual/gui/editing.qmd
create mode 100644 gui/images/unicode-encoded.svg
diff --git a/docs/manual/_quarto.yml b/docs/manual/_quarto.yml
index 4194c7a..dbbd2ed 100644
--- a/docs/manual/_quarto.yml
+++ b/docs/manual/_quarto.yml
@@ -32,6 +32,7 @@ book:
chapters:
- gui/new-project.qmd
- gui/reviewing-output.qmd
+ - gui/editing.qmd
- gui/options.qmd
- part: "Additional Features"
chapters:
diff --git a/docs/manual/_quarto.yml.in b/docs/manual/_quarto.yml.in
index 2fdbf50..88358d8 100644
--- a/docs/manual/_quarto.yml.in
+++ b/docs/manual/_quarto.yml.in
@@ -32,6 +32,7 @@ book:
chapters:
- gui/new-project.qmd
- gui/reviewing-output.qmd
+ - gui/editing.qmd
- gui/options.qmd
- part: "Additional Features"
chapters:
diff --git a/docs/manual/gui/editing.qmd b/docs/manual/gui/editing.qmd
new file mode 100644
index 0000000..f348775
--- /dev/null
+++ b/docs/manual/gui/editing.qmd
@@ -0,0 +1,41 @@
+```{r}
+#| include: false
+#| eval: true
+
+source('../R/appdown.r')
+```
+
+# Editing
+
+When a source file in the loaded in the editor and the editor is selected, the **Edit** section of the ribbon will become enabled.
+From here, you can edit the source file in the **Editor** and make use of these options from the ribbon.
+
+## Basic Operations
+
+Clipboard operations (e.g., `r keys("Cut")`, `r keys("Copy")`, and `r keys("Paste")`), `r keys("Undo")`, `r keys("Redo")`, and `r keys("Select All")` are all available from this section.
+
+## Insert
+
+From the `r keys("Insert")` button, options are available for inserting and converting content within the editor to fix various warnings.
+
+For example, to fix warnings about strings needing context, place the cursor into the editor in front of a resource loading call (e.g., `_("TABLE")`).
+Next, click the `r keys("Insert")` button on the ribbon and select **Translator Comment...**.
+Enter a comment that will explain to the translators what "TABLE" means in this context, providing guidance for how they should translate it.
+Click `r keys("OK")` and your comment with "TRANSLATORS: " prefixed will be inserted in front of the function call.
+("TRANSLATORS: " is the default tag that **gettext** looks for when extracting translator comments.)
+
+::: {.notesection data-latex=""}
+This warning is emitted when the option **Check for ambiguous strings that lack a translator comment** (from the **Source Code** settings) is checked.
+:::
+
+To fix warnings about extended ASCII characters needing to be encoded, select the text in the editor which contains these characters.
+Next, click the `r keys("Insert")` button on the ribbon and select **Encode Extended ASCII Characters...**.
+You will then be prompted about how the selection will be re-encoded.
+Click `r keys("OK")` and the selection will be replaced with the re-encoded content.
+
+As an example, if you have the string "Błąd" (Polish for "Error") in a source file, some legacy compilers may have difficulty processing it (even if encoded as UTF-8).
+By following the aforementioned steps, this will be re-encoded to "B\\U00000142\\U00000105d."
+
+::: {.notesection data-latex=""}
+This warning is emitted when the option **Unencoded extended ASCII characters** (from the **Additional Checks** settings) is checked.
+:::
diff --git a/docs/manual/gui/reviewing-output.qmd b/docs/manual/gui/reviewing-output.qmd
index 4e58268..fe47ed0 100644
--- a/docs/manual/gui/reviewing-output.qmd
+++ b/docs/manual/gui/reviewing-output.qmd
@@ -31,17 +31,7 @@ All instances of this warning will be removed from all files. Also, this check w
These options are also available by right clicking any warning and selecting them from the popup menu.
:::
-## Editing
-
-When a warning for a source file is selected, the **Edit** section of the ribbon will become enabled.
-From here, you can edit the source file in the **Editor** and use these options on the ribbon to edit it.
-For example, to fix warnings about strings needing context, place the cursor into the editor in front of a resource loading call (e.g., `_("TABLE")`).
-Next, click the `r keys("Insert")` button on the ribbon and select **Translator Comment**.
-Enter a comment that will explain to the translators what "TABLE" means in this context, providing guidance for how they should translate it.
-Click `r keys("OK")` and your comment with "TRANSLATORS: " prefixed will be inserted in front of the function call.
-("TRANSLATORS: " is the default tag that **gettext** looks for when extracting translator comments.)
-
## Exporting Results
To export all warnings, click the `r keys("Save")` button on the ribbon and select **Export Results**.
-From here, you can export the results to either a CSV or tab-delimited text file.
\ No newline at end of file
+From here, you can export the results to either a CSV or tab-delimited text file.
diff --git a/gui/images/unicode-encoded.svg b/gui/images/unicode-encoded.svg
new file mode 100644
index 0000000..bfa9dd8
--- /dev/null
+++ b/gui/images/unicode-encoded.svg
@@ -0,0 +1,117 @@
+
+
+
+
diff --git a/src/analyze.cpp b/src/analyze.cpp
index 8d9c7a1..3611208 100644
--- a/src/analyze.cpp
+++ b/src/analyze.cpp
@@ -13,7 +13,6 @@
#include "analyze.h"
#include
-#include
namespace i18n_check
{
diff --git a/src/gui/i18napp.cpp b/src/gui/i18napp.cpp
index 5496850..4705ed0 100644
--- a/src/gui/i18napp.cpp
+++ b/src/gui/i18napp.cpp
@@ -37,6 +37,7 @@ I18NArtProvider::I18NArtProvider()
{ L"ID_INSERT_TRANSLATOR_COMMENT", L"images/comment.svg" },
{ L"ID_CODE", L"images/code.svg" },
{ L"ID_TRANSLATIONS", L"images/translations.svg" },
+ { L"ID_CONVERT_TO_ENCODED_UNICODE", L"images/unicode-encoded.svg" },
{ L"ID_CHECK", L"images/check.svg" },
{ L"ID_FORMAT", L"images/format.svg" },
{ L"ID_DEBUG", L"images/bug.svg" },
diff --git a/src/gui/i18nframe.cpp b/src/gui/i18nframe.cpp
index 1bf121e..be8d9a0 100644
--- a/src/gui/i18nframe.cpp
+++ b/src/gui/i18nframe.cpp
@@ -398,6 +398,9 @@ void I18NFrame::InitControls()
Bind(
wxEVT_MENU, [this](wxCommandEvent& event) { OnInsertTranslatorComment(event); },
XRCID("ID_INSERT_TRANSLATOR_COMMENT"));
+ Bind(
+ wxEVT_MENU, [this](wxCommandEvent& event) { OnInsertEncodedUnicode(event); },
+ XRCID("ID_CONVERT_TO_ENCODED_UNICODE"));
Bind(
wxEVT_MENU,
[this]([[maybe_unused]] wxCommandEvent&)
@@ -765,11 +768,17 @@ void I18NFrame::OnInsert(wxRibbonButtonBarEvent& event)
{
wxMenu menu;
wxMenuItem* menuItem =
- new wxMenuItem(&menu, XRCID("ID_INSERT_TRANSLATOR_COMMENT"), _(L"Translator Comment"));
+ new wxMenuItem(&menu, XRCID("ID_INSERT_TRANSLATOR_COMMENT"), _(L"Translator Comment..."));
menuItem->SetBitmap(wxArtProvider::GetBitmap(L"ID_INSERT_TRANSLATOR_COMMENT", wxART_OTHER,
FromDIP(wxSize{ 16, 16 })));
menu.Append(menuItem);
+ menuItem = new wxMenuItem(&menu, XRCID("ID_CONVERT_TO_ENCODED_UNICODE"),
+ _(L"Encode Extended ASCII Characters..."));
+ menuItem->SetBitmap(wxArtProvider::GetBitmap(L"ID_CONVERT_TO_ENCODED_UNICODE", wxART_OTHER,
+ FromDIP(wxSize{ 16, 16 })));
+ menu.Append(menuItem);
+
event.PopupMenu(&menu);
}
@@ -1010,7 +1019,7 @@ void I18NFrame::OnInsertTranslatorComment([[maybe_unused]] wxCommandEvent&)
wxTextEntryDialog dialog(
this, _("Enter an explanation for a string that provides context for the translators:"),
_("Translator Comment"), wxString{}, wxTextEntryDialogStyle | wxTE_MULTILINE,
- wxDefaultPosition, wxWindow::FromDIP(wxSize{ 150, 250 }));
+ wxDefaultPosition, wxWindow::FromDIP(wxSize{ 175, 250 }));
if (dialog.ShowModal() != wxID_OK)
{
return;
@@ -1020,6 +1029,51 @@ void I18NFrame::OnInsertTranslatorComment([[maybe_unused]] wxCommandEvent&)
_DT(L"/* TRANSLATORS: ") + dialog.GetValue() + L" */");
}
+//------------------------------------------------------
+void I18NFrame::OnInsertEncodedUnicode([[maybe_unused]] wxCommandEvent&)
+ {
+ const std::wstring selText{ m_editor->GetSelectedText().wc_string() };
+ if (selText.empty())
+ {
+ wxMessageBox(_(L"No selection found. Please select a string in the editor to encode."),
+ _(L"No Selection"));
+ return;
+ }
+
+ std::wstringstream encoded;
+ bool encodingRequired{ false };
+ for (const auto& ch : selText)
+ {
+ if (ch > 127)
+ {
+ encoded << LR"(\U)" << std::setfill(L'0') << std::setw(8)
+ << std::uppercase << std::hex << static_cast(ch);
+ encodingRequired = true;
+ }
+ else
+ {
+ encoded << ch;
+ }
+ }
+
+ if (!encodingRequired)
+ {
+ wxMessageBox(
+ _(L"No extened ASCII characters found in the selection that need to be encoded."),
+ _(L"Encoding Not Required"));
+ return;
+ }
+
+ if (wxMessageBox(wxString::Format(
+ _(L"Replace the selected text:\n\n'%s'\n\nwith the following?\n\n'%s'"),
+ selText, encoded.str()),
+ _(L"Encode Extended ASCII Characters"),
+ wxYES_NO | wxYES_DEFAULT | wxICON_QUESTION) == wxYES)
+ {
+ m_editor->ReplaceSelection(encoded.str());
+ }
+ }
+
//------------------------------------------------------
void I18NFrame::OnExportResults([[maybe_unused]] wxCommandEvent&)
{
@@ -1116,7 +1170,7 @@ void I18NFrame::SaveSourceFileIfNeeded()
if (wxFileName{ m_activeSourceFile }.GetExt().CmpNoCase(L"rc") == 0)
{
std::wstring encoding{ L"utf-8" };
- const std::wstring& fileText = m_editor->GetText().wc_string();
+ const std::wstring fileText = m_editor->GetText().wc_string();
const std::wregex codePageRE{ _DT(LR"(#pragma code_page\(([0-9]+)\))") };
std::wsmatch matchResults;
if (std::regex_search(fileText.cbegin(), fileText.cend(), matchResults, codePageRE) &&
diff --git a/src/gui/i18nframe.h b/src/gui/i18nframe.h
index cc977c1..dc49322 100644
--- a/src/gui/i18nframe.h
+++ b/src/gui/i18nframe.h
@@ -60,6 +60,7 @@ class I18NFrame : public wxFrame
void OnSave([[maybe_unused]] wxCommandEvent&);
void OnExportResults([[maybe_unused]] wxCommandEvent&);
void OnInsertTranslatorComment([[maybe_unused]] wxCommandEvent&);
+ void OnInsertEncodedUnicode([[maybe_unused]] wxCommandEvent&);
void OnSaveMenu(wxRibbonButtonBarEvent& event);
void OnRefresh([[maybe_unused]] wxCommandEvent&);
void OnOpenSelectedFile([[maybe_unused]] wxCommandEvent&);