mirror of
https://github.com/goatcorp/Dalamud.git
synced 2025-12-13 12:14:16 +01:00
SeStringEvaluator: Fix HeadAll not capitalizing correctly (#2240)
* Fix obsoletes * Fix HeadAll not capitalizing correctly * Fix incorrect denoun cases in SeString Creator * Implement Utf8String.ToUpper in C# * Handle characters with accents too * Add remarks to ToUpper functions
This commit is contained in:
parent
f96e2ae37c
commit
499952b3d2
6 changed files with 138 additions and 9 deletions
|
|
@ -158,7 +158,7 @@ internal sealed class ClientState : IInternalDisposableService, IClientState
|
||||||
ConditionFlag.NormalConditions,
|
ConditionFlag.NormalConditions,
|
||||||
ConditionFlag.Jumping,
|
ConditionFlag.Jumping,
|
||||||
ConditionFlag.Mounted,
|
ConditionFlag.Mounted,
|
||||||
ConditionFlag.UsingParasol]);
|
ConditionFlag.UsingFashionAccessory]);
|
||||||
|
|
||||||
blockingFlag = blockingConditions.FirstOrDefault();
|
blockingFlag = blockingConditions.FirstOrDefault();
|
||||||
return blockingFlag == 0;
|
return blockingFlag == 0;
|
||||||
|
|
|
||||||
|
|
@ -939,9 +939,7 @@ internal class SeStringEvaluator : IServiceType, ISeStringEvaluator
|
||||||
|
|
||||||
if (p.Type == ReadOnlySePayloadType.Text)
|
if (p.Type == ReadOnlySePayloadType.Text)
|
||||||
{
|
{
|
||||||
context.Builder.Append(
|
context.Builder.Append(Encoding.UTF8.GetString(p.Body.Span).ToUpper(true, true, false, context.Language));
|
||||||
context.CultureInfo.TextInfo.ToTitleCase(Encoding.UTF8.GetString(p.Body.Span)));
|
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ using Dalamud.Game.Text.Noun.Enums;
|
||||||
using Dalamud.Interface.Utility.Raii;
|
using Dalamud.Interface.Utility.Raii;
|
||||||
|
|
||||||
using ImGuiNET;
|
using ImGuiNET;
|
||||||
|
|
||||||
using Lumina.Data;
|
using Lumina.Data;
|
||||||
using Lumina.Excel;
|
using Lumina.Excel;
|
||||||
using Lumina.Excel.Sheets;
|
using Lumina.Excel.Sheets;
|
||||||
|
|
@ -21,7 +22,7 @@ namespace Dalamud.Interface.Internal.Windows.Data.Widgets;
|
||||||
internal class NounProcessorWidget : IDataWindowWidget
|
internal class NounProcessorWidget : IDataWindowWidget
|
||||||
{
|
{
|
||||||
/// <summary>A list of German grammatical cases.</summary>
|
/// <summary>A list of German grammatical cases.</summary>
|
||||||
internal static readonly string[] GermanCases = ["Nominative", "Genitive", "Dative", "Accusative"];
|
internal static readonly string[] GermanCases = [string.Empty, "Nominative", "Genitive", "Dative", "Accusative"];
|
||||||
|
|
||||||
private static readonly Type[] NounSheets = [
|
private static readonly Type[] NounSheets = [
|
||||||
typeof(Aetheryte),
|
typeof(Aetheryte),
|
||||||
|
|
@ -156,7 +157,7 @@ internal class NounProcessorWidget : IDataWindowWidget
|
||||||
GrammaticalCase = grammaticalCase,
|
GrammaticalCase = grammaticalCase,
|
||||||
};
|
};
|
||||||
var output = nounProcessor.ProcessNoun(nounParams).ExtractText().Replace("\"", "\\\"");
|
var output = nounProcessor.ProcessNoun(nounParams).ExtractText().Replace("\"", "\\\"");
|
||||||
var caseParam = language == ClientLanguage.German ? $"(int)GermanCases.{GermanCases[grammaticalCase]}" : "1";
|
var caseParam = language == ClientLanguage.German ? $"(int)GermanCases.{GermanCases[grammaticalCase + 1]}" : "1";
|
||||||
sb.AppendLine($"new(nameof(LSheets.{sheetType.Name}), {this.rowId}, ClientLanguage.{language}, {this.amount}, (int){articleTypeEnumType.Name}.{Enum.GetName(articleTypeEnumType, articleType)}, {caseParam}, \"{output}\"),");
|
sb.AppendLine($"new(nameof(LSheets.{sheetType.Name}), {this.rowId}, ClientLanguage.{language}, {this.amount}, (int){articleTypeEnumType.Name}.{Enum.GetName(articleTypeEnumType, articleType)}, {caseParam}, \"{output}\"),");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1014,7 +1014,7 @@ internal class SeStringCreatorWidget : IDataWindowWidget
|
||||||
ImGui.TextUnformatted(Enum.GetName(articleTypeEnumType, u32));
|
ImGui.TextUnformatted(Enum.GetName(articleTypeEnumType, u32));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (macroCode is MacroCode.DeNoun && exprIdx == 4 && u32 is >= 0 and <= 3)
|
if (macroCode is MacroCode.DeNoun && exprIdx == 4 && u32 is >= 0 and <= 4)
|
||||||
{
|
{
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
ImGui.TextUnformatted(NounProcessorWidget.GermanCases[u32]);
|
ImGui.TextUnformatted(NounProcessorWidget.GermanCases[u32]);
|
||||||
|
|
|
||||||
|
|
@ -501,7 +501,7 @@ internal class AutoUpdateManager : IServiceType
|
||||||
condition.OnlyAny(ConditionFlag.NormalConditions,
|
condition.OnlyAny(ConditionFlag.NormalConditions,
|
||||||
ConditionFlag.Jumping,
|
ConditionFlag.Jumping,
|
||||||
ConditionFlag.Mounted,
|
ConditionFlag.Mounted,
|
||||||
ConditionFlag.UsingParasol);
|
ConditionFlag.UsingFashionAccessory);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsPluginManagerReady()
|
private bool IsPluginManagerReady()
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,8 @@
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
using Dalamud.Game;
|
||||||
|
|
||||||
using FFXIVClientStructs.FFXIV.Client.UI;
|
using FFXIVClientStructs.FFXIV.Client.UI;
|
||||||
|
|
||||||
|
|
@ -10,6 +13,9 @@ namespace Dalamud.Utility;
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static class StringExtensions
|
public static class StringExtensions
|
||||||
{
|
{
|
||||||
|
private static readonly string[] CommonExcludedWords = ["sas", "zos", "van", "nan", "tol", "deus", "mal", "de", "rem", "out", "yae", "bas", "cen", "quo", "viator", "la"];
|
||||||
|
private static readonly string[] EnglishExcludedWords = ["of", "the", "to", "and", "a", "an", "or", "at", "by", "for", "in", "on", "with", "from", .. CommonExcludedWords];
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// An extension method to chain usage of string.Format.
|
/// An extension method to chain usage of string.Format.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -77,7 +83,7 @@ public static class StringExtensions
|
||||||
public static string StripSoftHyphen(this string input) => input.Replace("\u00AD", string.Empty);
|
public static string StripSoftHyphen(this string input) => input.Replace("\u00AD", string.Empty);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Truncates the given string to the specified maximum number of characters,
|
/// Truncates the given string to the specified maximum number of characters,
|
||||||
/// appending an ellipsis if truncation occurs.
|
/// appending an ellipsis if truncation occurs.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="input">The string to truncate.</param>
|
/// <param name="input">The string to truncate.</param>
|
||||||
|
|
@ -88,4 +94,128 @@ public static class StringExtensions
|
||||||
{
|
{
|
||||||
return string.IsNullOrEmpty(input) || input.Length <= maxChars ? input : input[..maxChars] + ellipses;
|
return string.IsNullOrEmpty(input) || input.Length <= maxChars ? input : input[..maxChars] + ellipses;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converts the input string to uppercase based on specified options like capitalizing the first character,
|
||||||
|
/// normalizing vowels, and excluding certain words based on the selected language.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="input">The input string to be converted to uppercase.</param>
|
||||||
|
/// <param name="firstCharOnly">Whether to capitalize only the first character of the string.</param>
|
||||||
|
/// <param name="everyWord">Whether to capitalize the first letter of each word.</param>
|
||||||
|
/// <param name="normalizeVowels">Whether to normalize vowels to uppercase if they appear at the beginning of a word.</param>
|
||||||
|
/// <param name="language">The language context used to determine which words to exclude from capitalization.</param>
|
||||||
|
/// <returns>A new string with the appropriate characters converted to uppercase.</returns>
|
||||||
|
/// <remarks>This is a C# implementation of Client::System::String::Utf8String.ToUpper with word exclusion lists as used by the HeadAll macro.</remarks>
|
||||||
|
public static string ToUpper(this string input, bool firstCharOnly, bool everyWord, bool normalizeVowels, ClientLanguage language)
|
||||||
|
{
|
||||||
|
return ToUpper(input, firstCharOnly, everyWord, normalizeVowels, language switch
|
||||||
|
{
|
||||||
|
ClientLanguage.Japanese => [],
|
||||||
|
ClientLanguage.English => EnglishExcludedWords,
|
||||||
|
ClientLanguage.German => CommonExcludedWords,
|
||||||
|
ClientLanguage.French => CommonExcludedWords,
|
||||||
|
_ => [],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converts the input string to uppercase based on specified options like capitalizing the first character,
|
||||||
|
/// normalizing vowels, and excluding certain words based on the selected language.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="input">The input string to be converted to uppercase.</param>
|
||||||
|
/// <param name="firstCharOnly">Whether to capitalize only the first character of the string.</param>
|
||||||
|
/// <param name="everyWord">Whether to capitalize the first letter of each word.</param>
|
||||||
|
/// <param name="normalizeVowels">Whether to normalize vowels to uppercase if they appear at the beginning of a word.</param>
|
||||||
|
/// <param name="excludedWords">A list of words to exclude from being capitalized. Words in this list will remain lowercase.</param>
|
||||||
|
/// <returns>A new string with the appropriate characters converted to uppercase.</returns>
|
||||||
|
/// <remarks>This is a C# implementation of Client::System::String::Utf8String.ToUpper.</remarks>
|
||||||
|
public static string ToUpper(this string input, bool firstCharOnly, bool everyWord, bool normalizeVowels, ReadOnlySpan<string> excludedWords)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(input))
|
||||||
|
return input;
|
||||||
|
|
||||||
|
var builder = new StringBuilder(input);
|
||||||
|
var isWordBeginning = true;
|
||||||
|
var length = firstCharOnly && !everyWord ? 1 : builder.Length;
|
||||||
|
|
||||||
|
for (var i = 0; i < length; i++)
|
||||||
|
{
|
||||||
|
var ch = builder[i];
|
||||||
|
|
||||||
|
if (ch == ' ')
|
||||||
|
{
|
||||||
|
isWordBeginning = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (firstCharOnly && !isWordBeginning)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Basic ASCII a-z
|
||||||
|
if (ch >= 'a' && ch <= 'z')
|
||||||
|
{
|
||||||
|
var substr = builder.ToString(i, builder.Length - i);
|
||||||
|
var isExcluded = false;
|
||||||
|
|
||||||
|
// Do not exclude words at the beginning
|
||||||
|
if (i > 0)
|
||||||
|
{
|
||||||
|
foreach (var excludedWord in excludedWords)
|
||||||
|
{
|
||||||
|
if (substr.StartsWith(excludedWord + " ", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
isExcluded = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isExcluded)
|
||||||
|
{
|
||||||
|
builder[i] = char.ToUpperInvariant(ch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Special œ → Œ
|
||||||
|
else if (ch == 'œ')
|
||||||
|
{
|
||||||
|
builder[i] = 'Œ';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Characters with accents
|
||||||
|
else if (ch >= 'à' && ch <= 'ý' && ch != '÷')
|
||||||
|
{
|
||||||
|
builder[i] = char.ToUpperInvariant(ch);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Normalize vowels with accents
|
||||||
|
else if (normalizeVowels && isWordBeginning)
|
||||||
|
{
|
||||||
|
if ("àáâãäå".Contains(ch))
|
||||||
|
{
|
||||||
|
builder[i] = 'A';
|
||||||
|
}
|
||||||
|
else if ("èéêë".Contains(ch))
|
||||||
|
{
|
||||||
|
builder[i] = 'E';
|
||||||
|
}
|
||||||
|
else if ("ìíîï".Contains(ch))
|
||||||
|
{
|
||||||
|
builder[i] = 'I';
|
||||||
|
}
|
||||||
|
else if ("òóôõö".Contains(ch))
|
||||||
|
{
|
||||||
|
builder[i] = 'O';
|
||||||
|
}
|
||||||
|
else if ("ùúûü".Contains(ch))
|
||||||
|
{
|
||||||
|
builder[i] = 'U';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
isWordBeginning = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder.ToString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue