diff --git a/Dalamud/Game/Gui/ChatGui.cs b/Dalamud/Game/Gui/ChatGui.cs
index 2361ec653..3c6ed2fc1 100644
--- a/Dalamud/Game/Gui/ChatGui.cs
+++ b/Dalamud/Game/Gui/ChatGui.cs
@@ -62,7 +62,7 @@ internal sealed unsafe class ChatGui : IInternalDisposableService, IChatGui
this.populateItemLinkHook.Enable();
this.interactableLinkClickedHook.Enable();
}
-
+
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
private delegate uint PrintMessageDelegate(RaptureLogModule* manager, XivChatType chatType, Utf8String* sender, Utf8String* message, int timestamp, byte silent);
@@ -122,31 +122,31 @@ internal sealed unsafe class ChatGui : IInternalDisposableService, IChatGui
{
this.chatQueue.Enqueue(chat);
}
-
+
///
public void Print(string message, string? messageTag = null, ushort? tagColor = null)
{
this.PrintTagged(message, this.configuration.GeneralChatType, messageTag, tagColor);
}
-
+
///
public void Print(SeString message, string? messageTag = null, ushort? tagColor = null)
{
this.PrintTagged(message, this.configuration.GeneralChatType, messageTag, tagColor);
}
-
+
///
public void PrintError(string message, string? messageTag = null, ushort? tagColor = null)
{
this.PrintTagged(message, XivChatType.Urgent, messageTag, tagColor);
}
-
+
///
public void PrintError(SeString message, string? messageTag = null, ushort? tagColor = null)
{
this.PrintTagged(message, XivChatType.Urgent, messageTag, tagColor);
}
-
+
///
/// Process a chat queue.
///
@@ -155,9 +155,29 @@ internal sealed unsafe class ChatGui : IInternalDisposableService, IChatGui
while (this.chatQueue.Count > 0)
{
var chat = this.chatQueue.Dequeue();
+ var replacedMessage = new SeStringBuilder();
+
+ // Normalize Unicode NBSP to the built-in one, as the former won't renderl
+ foreach (var payload in chat.Message.Payloads)
+ {
+ if (payload is TextPayload { Text: not null } textPayload)
+ {
+ var split = textPayload.Text.Split("\u202f"); // NARROW NO-BREAK SPACE
+ for (var i = 0; i < split.Length; i++)
+ {
+ replacedMessage.AddText(split[i]);
+ if (i + 1 < split.Length)
+ replacedMessage.Add(new RawPayload([0x02, (byte)Lumina.Text.Payloads.PayloadType.Indent, 0x01, 0x03]));
+ }
+ }
+ else
+ {
+ replacedMessage.Add(payload);
+ }
+ }
var sender = Utf8String.FromSequence(chat.Name.Encode());
- var message = Utf8String.FromSequence(chat.Message.Encode());
+ var message = Utf8String.FromSequence(replacedMessage.BuiltString.Encode());
this.HandlePrintMessageDetour(RaptureLogModule.Instance(), chat.Type, sender, message, (int)chat.SenderId, (byte)(chat.Parameters != 0 ? 1 : 0));
@@ -194,7 +214,7 @@ internal sealed unsafe class ChatGui : IInternalDisposableService, IChatGui
lock (this.dalamudLinkHandlers)
{
var changed = false;
-
+
foreach (var handler in this.RegisteredLinkHandlers.Keys.Where(k => k.PluginName == pluginName))
changed |= this.dalamudLinkHandlers.Remove(handler);
if (changed)
@@ -231,18 +251,18 @@ internal sealed unsafe class ChatGui : IInternalDisposableService, IChatGui
builder.AddText($"[{tag}] ");
}
}
-
+
this.Print(new XivChatEntry
{
Message = builder.AddText(message).Build(),
Type = channel,
});
}
-
+
private void PrintTagged(SeString message, XivChatType channel, string? tag, ushort? color)
{
var builder = new SeStringBuilder();
-
+
if (!tag.IsNullOrEmpty())
{
if (color is not null)
@@ -254,7 +274,7 @@ internal sealed unsafe class ChatGui : IInternalDisposableService, IChatGui
builder.AddText($"[{tag}] ");
}
}
-
+
this.Print(new XivChatEntry
{
Message = builder.Build().Append(message),
@@ -425,16 +445,16 @@ internal class ChatGuiPluginScoped : IInternalDisposableService, IChatGui
this.chatGuiService.ChatMessageHandled += this.OnMessageHandledForward;
this.chatGuiService.ChatMessageUnhandled += this.OnMessageUnhandledForward;
}
-
+
///
public event IChatGui.OnMessageDelegate? ChatMessage;
-
+
///
public event IChatGui.OnCheckMessageHandledDelegate? CheckMessageHandled;
-
+
///
public event IChatGui.OnMessageHandledDelegate? ChatMessageHandled;
-
+
///
public event IChatGui.OnMessageUnhandledDelegate? ChatMessageUnhandled;
@@ -460,23 +480,23 @@ internal class ChatGuiPluginScoped : IInternalDisposableService, IChatGui
this.ChatMessageHandled = null;
this.ChatMessageUnhandled = null;
}
-
+
///
public void Print(XivChatEntry chat)
=> this.chatGuiService.Print(chat);
-
+
///
- public void Print(string message, string? messageTag = null, ushort? tagColor = null)
+ public void Print(string message, string? messageTag = null, ushort? tagColor = null)
=> this.chatGuiService.Print(message, messageTag, tagColor);
///
public void Print(SeString message, string? messageTag = null, ushort? tagColor = null)
=> this.chatGuiService.Print(message, messageTag, tagColor);
-
+
///
public void PrintError(string message, string? messageTag = null, ushort? tagColor = null)
=> this.chatGuiService.PrintError(message, messageTag, tagColor);
-
+
///
public void PrintError(SeString message, string? messageTag = null, ushort? tagColor = null)
=> this.chatGuiService.PrintError(message, messageTag, tagColor);