diff --git a/runelite-client/src/main/java/net/runelite/client/game/chatbox/ChatboxTextInput.java b/runelite-client/src/main/java/net/runelite/client/game/chatbox/ChatboxTextInput.java index c8b1a3e846..2bc0bfde5b 100644 --- a/runelite-client/src/main/java/net/runelite/client/game/chatbox/ChatboxTextInput.java +++ b/runelite-client/src/main/java/net/runelite/client/game/chatbox/ChatboxTextInput.java @@ -51,6 +51,7 @@ import net.runelite.api.widgets.WidgetTextAlignment; import net.runelite.client.callback.ClientThread; import net.runelite.client.input.KeyListener; import net.runelite.client.input.MouseListener; +import net.runelite.client.util.Text; @Slf4j public class ChatboxTextInput extends ChatboxInput implements KeyListener, MouseListener @@ -233,9 +234,9 @@ public class ChatboxTextInput extends ChatboxInput implements KeyListener, Mouse { Widget container = chatboxPanelManager.getContainerWidget(); - String lt = value.substring(0, this.cursor); - String mt = value.substring(this.cursor, this.cursorEnd); - String rt = value.substring(this.cursorEnd); + String lt = Text.escapeJagex(value.substring(0, this.cursor)); + String mt = Text.escapeJagex(value.substring(this.cursor, this.cursorEnd)); + String rt = Text.escapeJagex(value.substring(this.cursorEnd)); Widget leftText = container.createChild(-1, WidgetType.TEXT); Widget cursor = container.createChild(-1, WidgetType.RECTANGLE); @@ -332,9 +333,9 @@ public class ChatboxTextInput extends ChatboxInput implements KeyListener, Mouse // `i` is used to track max execution time incase there is a font with ligature width data that causes this to fail for (int i = tsValue.length(); i >= 0 && charIndex >= 0 && charIndex <= tsValue.length(); i--) { - int lcx = charIndex > 0 ? font.getTextWidth(tsValue.substring(0, charIndex - 1)) : 0; - int mcx = font.getTextWidth(tsValue.substring(0, charIndex)); - int rcx = charIndex + 1 <= tsValue.length() ? font.getTextWidth(tsValue.substring(0, charIndex + 1)) : mcx; + int lcx = charIndex > 0 ? font.getTextWidth(Text.escapeJagex(tsValue.substring(0, charIndex - 1))) : 0; + int mcx = font.getTextWidth(Text.escapeJagex(tsValue.substring(0, charIndex))); + int rcx = charIndex + 1 <= tsValue.length() ? font.getTextWidth(Text.escapeJagex(tsValue.substring(0, charIndex + 1))) : mcx; int leftBound = (lcx + mcx) / 2; int rightBound = (mcx + rcx) / 2; diff --git a/runelite-client/src/main/java/net/runelite/client/util/Text.java b/runelite-client/src/main/java/net/runelite/client/util/Text.java index 72be89f3b4..9f73e947a6 100644 --- a/runelite-client/src/main/java/net/runelite/client/util/Text.java +++ b/runelite-client/src/main/java/net/runelite/client/util/Text.java @@ -36,10 +36,10 @@ public class Text private static final Pattern TAG_REGEXP = Pattern.compile("<[^>]*>"); /** - * Removes all tags from the given `str`. + * Removes all tags from the given string. * * @param str The string to remove tags from. - * @return The given `str` with all tags removed from it. + * @return The given string with all tags removed from it. */ public static String removeTags(String str) { @@ -70,7 +70,7 @@ public class Text } /** - * In addition to removing all tags, replaces all
delimited text with spaces and all multiple continuous + * In addition to removing all tags, replaces all <br> delimited text with spaces and all multiple continuous * spaces with single space * * @param str The string to sanitize @@ -83,4 +83,35 @@ public class Text .replaceAll("
", " ") .replaceAll("[ ]+", " ")); } + + /** + * Escapes a string for widgets, replacing < and > with their escaped counterparts + */ + public static String escapeJagex(String str) + { + StringBuilder out = new StringBuilder(str.length()); + + for (int i = 0; i < str.length(); i++) + { + char c = str.charAt(i); + if (c == '<') + { + out.append(""); + } + else if (c == '>') + { + out.append(""); + } + else if (c == '\n') + { + out.append("
"); + } + else if (c != '\r') + { + out.append(c); + } + } + + return out.toString(); + } } diff --git a/runelite-mixins/src/main/java/net/runelite/mixins/ScriptVMMixin.java b/runelite-mixins/src/main/java/net/runelite/mixins/ScriptVMMixin.java index 7293f9daa1..29f632576a 100644 --- a/runelite-mixins/src/main/java/net/runelite/mixins/ScriptVMMixin.java +++ b/runelite-mixins/src/main/java/net/runelite/mixins/ScriptVMMixin.java @@ -119,7 +119,14 @@ public abstract class ScriptVMMixin implements RSClient Object[] arguments = event.getArguments(); if (arguments != null && arguments.length > 0 && arguments[0] instanceof JavaScriptCallback) { - ((JavaScriptCallback) arguments[0]).run(event); + try + { + ((JavaScriptCallback) arguments[0]).run(event); + } + catch (Exception e) + { + client.getLogger().error("Error in JavaScriptCallback", e); + } return; }