mirror of
https://github.com/goatcorp/Dalamud.git
synced 2025-12-12 10:17:22 +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.Jumping,
|
||||
ConditionFlag.Mounted,
|
||||
ConditionFlag.UsingParasol]);
|
||||
ConditionFlag.UsingFashionAccessory]);
|
||||
|
||||
blockingFlag = blockingConditions.FirstOrDefault();
|
||||
return blockingFlag == 0;
|
||||
|
|
|
|||
|
|
@ -939,9 +939,7 @@ internal class SeStringEvaluator : IServiceType, ISeStringEvaluator
|
|||
|
||||
if (p.Type == ReadOnlySePayloadType.Text)
|
||||
{
|
||||
context.Builder.Append(
|
||||
context.CultureInfo.TextInfo.ToTitleCase(Encoding.UTF8.GetString(p.Body.Span)));
|
||||
|
||||
context.Builder.Append(Encoding.UTF8.GetString(p.Body.Span).ToUpper(true, true, false, context.Language));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ using Dalamud.Game.Text.Noun.Enums;
|
|||
using Dalamud.Interface.Utility.Raii;
|
||||
|
||||
using ImGuiNET;
|
||||
|
||||
using Lumina.Data;
|
||||
using Lumina.Excel;
|
||||
using Lumina.Excel.Sheets;
|
||||
|
|
@ -21,7 +22,7 @@ namespace Dalamud.Interface.Internal.Windows.Data.Widgets;
|
|||
internal class NounProcessorWidget : IDataWindowWidget
|
||||
{
|
||||
/// <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 = [
|
||||
typeof(Aetheryte),
|
||||
|
|
@ -156,7 +157,7 @@ internal class NounProcessorWidget : IDataWindowWidget
|
|||
GrammaticalCase = grammaticalCase,
|
||||
};
|
||||
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}\"),");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1014,7 +1014,7 @@ internal class SeStringCreatorWidget : IDataWindowWidget
|
|||
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.TextUnformatted(NounProcessorWidget.GermanCases[u32]);
|
||||
|
|
|
|||
|
|
@ -501,7 +501,7 @@ internal class AutoUpdateManager : IServiceType
|
|||
condition.OnlyAny(ConditionFlag.NormalConditions,
|
||||
ConditionFlag.Jumping,
|
||||
ConditionFlag.Mounted,
|
||||
ConditionFlag.UsingParasol);
|
||||
ConditionFlag.UsingFashionAccessory);
|
||||
}
|
||||
|
||||
private bool IsPluginManagerReady()
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
|
||||
using Dalamud.Game;
|
||||
|
||||
using FFXIVClientStructs.FFXIV.Client.UI;
|
||||
|
||||
|
|
@ -10,6 +13,9 @@ namespace Dalamud.Utility;
|
|||
/// </summary>
|
||||
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>
|
||||
/// An extension method to chain usage of string.Format.
|
||||
/// </summary>
|
||||
|
|
@ -77,7 +83,7 @@ public static class StringExtensions
|
|||
public static string StripSoftHyphen(this string input) => input.Replace("\u00AD", string.Empty);
|
||||
|
||||
/// <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.
|
||||
/// </summary>
|
||||
/// <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;
|
||||
}
|
||||
|
||||
/// <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