Skip to content

Commit

Permalink
Remove invalid unicode sequences from text copied from clipboard/WebS…
Browse files Browse the repository at this point in the history
…ocket
  • Loading branch information
rampaa committed Jan 26, 2024
1 parent 5e4ca11 commit 691cf92
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 25 deletions.
2 changes: 2 additions & 0 deletions JL.Core/CoreConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ public static class CoreConfig
public static int LookupRate { get; set; } = 0;
public static bool CaptureTextFromClipboard { get; set; } = true;
public static bool CaptureTextFromWebSocket { get; set; } = false;
public static bool TextBoxTrimWhiteSpaceCharacters { get; set; } = true;
public static bool TextBoxRemoveNewlines { get; set; } = false;
public static Uri WebSocketUri { get; set; } = new("ws://127.0.0.1:6677");
public static int AudioVolume { get; set; } = 100;
}
93 changes: 93 additions & 0 deletions JL.Core/Utilities/TextUtils.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
using System.Text;

namespace JL.Core.Utilities;
public class TextUtils
{
private static int FirstInvalidUnicodeSequenceIndex(string text)
{
for (int i = 0; i < text.Length; i++)
{
char c = text[i];

if (c < '\ud800')
{
continue;
}
else if (c is '\uFFFE' || char.IsLowSurrogate(c))
{
return i;
}
else if (char.IsHighSurrogate(c))
{
if (i + 1 >= text.Length || !char.IsLowSurrogate(text[i + 1]))
{
return i;
}
else
{
++i;
}
}
}

return -1;
}

private static string RemoveInvalidUnicodeSequences(string text, int index)
{
StringBuilder sb = new(text[..index], text.Length - 1);

for (int i = index + 1; i < text.Length; i++)
{
char c = text[i];

if (c < '\ud800')
{
_ = sb.Append(c);
}
else if (c is '\uFFFE' || char.IsLowSurrogate(c))
{
continue;
}
else if (char.IsHighSurrogate(c))
{
if (i + 1 >= text.Length || !char.IsLowSurrogate(text[i + 1]))
{
continue;
}
else
{
_ = sb.Append(c).Append(text[i + 1]);
++i;
}
}
else
{
_ = sb.Append(c);
}
}

return sb.ToString();
}

public static string SanitizeText(string text)
{
int firstInvalidUnicodeCharIndex = FirstInvalidUnicodeSequenceIndex(text);
if (firstInvalidUnicodeCharIndex is not -1)
{
text = RemoveInvalidUnicodeSequences(text, firstInvalidUnicodeCharIndex);
}

if (CoreConfig.TextBoxTrimWhiteSpaceCharacters)
{
text = text.Trim();
}

if (CoreConfig.TextBoxRemoveNewlines)
{
text = text.ReplaceLineEndings("");
}

return text;
}
}
14 changes: 6 additions & 8 deletions JL.Windows/ConfigManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,6 @@ internal static class ConfigManager
public static bool TextOnlyVisibleOnHover { get; set; } = false;
public static bool ChangeMainWindowBackgroundOpacityOnUnhover { get; private set; } = false;
public static double MainWindowBackgroundOpacityOnUnhover { get; private set; } = 0.2; // 0.2-100
public static bool TextBoxTrimWhiteSpaceCharacters { get; private set; } = true;
public static bool TextBoxRemoveNewlines { get; private set; } = false;
public static bool TextBoxIsReadOnly { get; set; } = true;
private static bool TextBoxApplyDropShadowEffect { get; set; } = true;
public static bool OnlyCaptureTextWithJapaneseChars { get; private set; } = true;
Expand Down Expand Up @@ -284,8 +282,8 @@ public static void ApplyPreferences()
FixedPopupPositioning = GetValueFromConfig(config, FixedPopupPositioning, nameof(FixedPopupPositioning), bool.TryParse);
ChangeMainWindowBackgroundOpacityOnUnhover = GetValueFromConfig(config, ChangeMainWindowBackgroundOpacityOnUnhover, nameof(ChangeMainWindowBackgroundOpacityOnUnhover), bool.TryParse);
TextOnlyVisibleOnHover = GetValueFromConfig(config, TextOnlyVisibleOnHover, nameof(TextOnlyVisibleOnHover), bool.TryParse);
TextBoxTrimWhiteSpaceCharacters = GetValueFromConfig(config, TextBoxTrimWhiteSpaceCharacters, nameof(TextBoxTrimWhiteSpaceCharacters), bool.TryParse);
TextBoxRemoveNewlines = GetValueFromConfig(config, TextBoxRemoveNewlines, nameof(TextBoxRemoveNewlines), bool.TryParse);
CoreConfig.TextBoxTrimWhiteSpaceCharacters = GetValueFromConfig(config, CoreConfig.TextBoxTrimWhiteSpaceCharacters, nameof(CoreConfig.TextBoxTrimWhiteSpaceCharacters), bool.TryParse);
CoreConfig.TextBoxRemoveNewlines = GetValueFromConfig(config, CoreConfig.TextBoxRemoveNewlines, nameof(CoreConfig.TextBoxRemoveNewlines), bool.TryParse);
OnlyCaptureTextWithJapaneseChars = GetValueFromConfig(config, OnlyCaptureTextWithJapaneseChars, nameof(OnlyCaptureTextWithJapaneseChars), bool.TryParse);
DisableLookupsForNonJapaneseCharsInMainWindow = GetValueFromConfig(config, DisableLookupsForNonJapaneseCharsInMainWindow, nameof(DisableLookupsForNonJapaneseCharsInMainWindow), bool.TryParse);
MainWindowFocusOnHover = GetValueFromConfig(config, MainWindowFocusOnHover, nameof(MainWindowFocusOnHover), bool.TryParse);
Expand Down Expand Up @@ -851,8 +849,8 @@ public static void LoadPreferences(PreferencesWindow preferenceWindow)

preferenceWindow.TextBoxIsReadOnlyCheckBox.IsChecked = TextBoxIsReadOnly;
preferenceWindow.AlwaysShowMainTextBoxCaretCheckBox.IsChecked = AlwaysShowMainTextBoxCaret;
preferenceWindow.TextBoxTrimWhiteSpaceCharactersCheckBox.IsChecked = TextBoxTrimWhiteSpaceCharacters;
preferenceWindow.TextBoxRemoveNewlinesCheckBox.IsChecked = TextBoxRemoveNewlines;
preferenceWindow.TextBoxTrimWhiteSpaceCharactersCheckBox.IsChecked = CoreConfig.TextBoxTrimWhiteSpaceCharacters;
preferenceWindow.TextBoxRemoveNewlinesCheckBox.IsChecked = CoreConfig.TextBoxRemoveNewlines;
preferenceWindow.TextBoxApplyDropShadowEffectCheckBox.IsChecked = TextBoxApplyDropShadowEffect;
preferenceWindow.CaptureTextFromClipboardCheckBox.IsChecked = CoreConfig.CaptureTextFromClipboard;
preferenceWindow.CaptureTextFromWebSocketCheckBox.IsChecked = CoreConfig.CaptureTextFromWebSocket;
Expand Down Expand Up @@ -1050,9 +1048,9 @@ public static async Task SavePreferences(PreferencesWindow preferenceWindow)
preferenceWindow.TextBoxIsReadOnlyCheckBox.IsChecked.ToString();
settings[nameof(AlwaysShowMainTextBoxCaret)].Value =
preferenceWindow.AlwaysShowMainTextBoxCaretCheckBox.IsChecked.ToString();
settings[nameof(TextBoxTrimWhiteSpaceCharacters)].Value =
settings[nameof(CoreConfig.TextBoxTrimWhiteSpaceCharacters)].Value =
preferenceWindow.TextBoxTrimWhiteSpaceCharactersCheckBox.IsChecked.ToString();
settings[nameof(TextBoxRemoveNewlines)].Value =
settings[nameof(CoreConfig.TextBoxRemoveNewlines)].Value =
preferenceWindow.TextBoxRemoveNewlinesCheckBox.IsChecked.ToString();
settings[nameof(TextBoxApplyDropShadowEffect)].Value =
preferenceWindow.TextBoxApplyDropShadowEffectCheckBox.IsChecked.ToString();
Expand Down
19 changes: 2 additions & 17 deletions JL.Windows/GUI/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ private void CopyFromClipboard()
gotTextFromClipboard = true;
if (!ConfigManager.OnlyCaptureTextWithJapaneseChars || JapaneseUtils.JapaneseRegex.IsMatch(text))
{
text = SanitizeText(text);
text = TextUtils.SanitizeText(text);

if (WindowState is not WindowState.Minimized)
{
Expand All @@ -138,7 +138,7 @@ public void CopyFromWebSocket(string text)
{
if (!ConfigManager.OnlyCaptureTextWithJapaneseChars || JapaneseUtils.JapaneseRegex.IsMatch(text))
{
text = SanitizeText(text);
text = TextUtils.SanitizeText(text);

Dispatcher.Invoke(() =>
{
Expand All @@ -153,21 +153,6 @@ public void CopyFromWebSocket(string text)
}
}

private static string SanitizeText(string text)
{
if (ConfigManager.TextBoxTrimWhiteSpaceCharacters)
{
text = text.Trim();
}

if (ConfigManager.TextBoxRemoveNewlines)
{
text = text.ReplaceLineEndings("");
}

return text;
}

private void HandlePostCopy(string text)
{
Dispatcher.Invoke(() =>
Expand Down

0 comments on commit 691cf92

Please sign in to comment.