From 31ea78499825ddf170439062a308e74980d2a070 Mon Sep 17 00:00:00 2001 From: bigguy345 Date: Wed, 17 Dec 2025 14:33:17 +0200 Subject: [PATCH] Fixed text cursor movement bugs --- .../client/gui/util/GuiScriptTextArea.java | 31 +++++----- .../gui/util/script/JavaTextContainer.java | 56 +++++++++---------- 2 files changed, 44 insertions(+), 43 deletions(-) diff --git a/src/main/java/noppes/npcs/client/gui/util/GuiScriptTextArea.java b/src/main/java/noppes/npcs/client/gui/util/GuiScriptTextArea.java index a30410b76..22de3e54b 100644 --- a/src/main/java/noppes/npcs/client/gui/util/GuiScriptTextArea.java +++ b/src/main/java/noppes/npcs/client/gui/util/GuiScriptTextArea.java @@ -170,8 +170,9 @@ public class GuiScriptTextArea extends GuiNpcTextField { int yPos = y + (i - scrolledLine) * container.lineHeight + 1; data.drawString(x + 1, yPos, 0xFFe0e0e0); - if (active && isEnabled() && (cursorCounter / 6) % 2 == 0 && cursorPosition >= data.start && cursorPosition <= data.end) { - int posX = x + ClientProxy.Font.width(line.substring(0, cursorPosition - data.start)); + if (active && isEnabled() && (cursorCounter / 6) % 2 == 0 && (cursorPosition >= data.start && cursorPosition < data.end || (i == list.size() - 1 && cursorPosition == text.length()))) { + int posX = x + ClientProxy.Font.width( + line.substring(0, Math.min(cursorPosition - data.start, line.length()))); drawRect(posX + 1, yPos, posX + 2, yPos + 1 + container.lineHeight, -3092272); } } @@ -270,6 +271,14 @@ public class GuiScriptTextArea extends GuiNpcTextField { if (!isEnabled()) return false; + LineData currentLine = null; + for (LineData line : this.container.lines) { + if (startSelection >= line.start && startSelection <= line.end) { + currentLine = line; + break; + } + } + String original = text; if (i == Keyboard.KEY_LEFT) { int j = 1; @@ -281,7 +290,8 @@ public class GuiScriptTextArea extends GuiNpcTextField { j = cursorPosition - m.start(); } } - setCursor(cursorPosition - j, GuiScreen.isShiftKeyDown()); + int newPos = Math.max(cursorPosition - j, 0); + setCursor(newPos, GuiScreen.isShiftKeyDown()); return true; } if (i == Keyboard.KEY_RIGHT) { @@ -292,7 +302,8 @@ public class GuiScriptTextArea extends GuiNpcTextField { j = m.start(); } } - setCursor(cursorPosition + j, GuiScreen.isShiftKeyDown()); + int newPos = Math.min(cursorPosition + j, text.length()); //-2 for the \n + setCursor(newPos, GuiScreen.isShiftKeyDown()); return true; } if (i == Keyboard.KEY_UP) { @@ -354,14 +365,6 @@ public class GuiScriptTextArea extends GuiNpcTextField { if (i == Keyboard.KEY_BACK) { if (startSelection == endSelection && startSelection > 0) { // Check if we should remove an empty/whitespace-only line - LineData currentLine = null; - for (LineData line : this.container.lines) { - if (startSelection >= line.start && startSelection <= line.end) { - currentLine = line; - break; - } - } - if (currentLine != null) { // Check if cursor is at line start or after only whitespace String beforeCursor = text.substring(currentLine.start, startSelection); @@ -373,7 +376,7 @@ public class GuiScriptTextArea extends GuiNpcTextField { if (atLineStartOrWhitespace && lineOnlyWhitespace && currentLine.start > 0) { // Remove the entire line including newline String before = text.substring(0, currentLine.start - 1); // -1 to include the newline before - String after = text.substring(currentLine.end); + String after = currentLine.end + 1 > text.length() ? "" : text.substring(currentLine.end + 1); setText(before + after); endSelection = cursorPosition = startSelection = currentLine.start - 1; return true; @@ -639,6 +642,8 @@ public class GuiScriptTextArea extends GuiNpcTextField { } private int cursorDown() { + if (cursorPosition == text.length()) + return cursorPosition; for (int i = 0; i < this.container.lines.size(); ++i) { LineData data = (LineData) this.container.lines.get(i); if (this.cursorPosition >= data.start && this.cursorPosition < data.end) { diff --git a/src/main/java/noppes/npcs/client/gui/util/script/JavaTextContainer.java b/src/main/java/noppes/npcs/client/gui/util/script/JavaTextContainer.java index cc494dd32..30fff9ccf 100644 --- a/src/main/java/noppes/npcs/client/gui/util/script/JavaTextContainer.java +++ b/src/main/java/noppes/npcs/client/gui/util/script/JavaTextContainer.java @@ -57,40 +57,29 @@ public class JavaTextContainer extends TextContainer { lineHeight = ClientProxy.Font.height(); if (lineHeight == 0) lineHeight = 12; - - lines.clear(); - String[] split = text.split("\n"); - int charIndex = 0; - - for (String rawLine : split) { - StringBuilder currentLine = new StringBuilder(); - int startIndex = charIndex; + int totalChars = 0; + for (String l : split) { + StringBuilder line = new StringBuilder(); + Matcher m = regexWord.matcher(l); int i = 0; - Matcher m = Pattern.compile(".").matcher(rawLine); // iterate each char while (m.find()) { - String c = rawLine.substring(m.start(), m.end()); - if (ClientProxy.Font.width(currentLine.toString() + c) > width - 10) { - LineData lineData = new LineData(currentLine.toString(), startIndex, - startIndex + currentLine.length()); - startIndex += currentLine.length(); - lines.add(lineData); - currentLine = new StringBuilder(); + String word = l.substring(i, m.start()); + if (ClientProxy.Font.width(line + word) > width - 10) { + lines.add(new LineData(line.toString(), totalChars, totalChars + line.length())); + totalChars += line.length(); + line = new StringBuilder(); } - currentLine.append(c); - i = m.end(); + line.append(word); + i = m.start(); } + lines.add(new LineData(line.toString(), totalChars, totalChars + line.length() + 1)); - if (currentLine.length() > 0) { - LineData lineData = new LineData(currentLine.toString(), startIndex, startIndex + currentLine.length()); - lines.add(lineData); - } - - charIndex += rawLine.length() + 1; // +1 for newline + totalChars += line.length() + 1; } - - totalHeight = lines.size() * lineHeight; + linesCount = lines.size(); + totalHeight = linesCount * lineHeight; visibleLines = Math.max(height / lineHeight, 1); } @@ -202,21 +191,28 @@ public class JavaTextContainer extends TextContainer { int tokenStart = Math.max(mark.start, line.start); int tokenEnd = Math.min(mark.end, line.end); + tokenStart = Math.max(0, Math.min(tokenStart, text.length())); + tokenEnd = Math.max(0, Math.min(tokenEnd, text.length())); + // plain text before token if (cursor < tokenStart) { + int end = Math.min(tokenStart, text.length()); line.tokens.add( - new Token(text.substring(cursor, tokenStart), TokenType.DEFAULT, cursor, tokenStart)); + new Token(text.substring(cursor, end), TokenType.DEFAULT, cursor, end)); } // token text - line.tokens.add(new Token(text.substring(tokenStart, tokenEnd), mark.type, tokenStart, tokenEnd)); + if (tokenStart < tokenEnd) { + line.tokens.add(new Token(text.substring(tokenStart, Math.min(tokenEnd, text.length())), mark.type, tokenStart, Math.min(tokenEnd, text.length()))); + } cursor = tokenEnd; } // trailing plain text if (cursor < line.end) { - line.tokens.add(new Token(text.substring(cursor, line.end), TokenType.DEFAULT, cursor, line.end)); + int end = Math.min(line.end, text.length()); + line.tokens.add(new Token(text.substring(cursor, end), TokenType.DEFAULT, cursor, end)); } } } @@ -301,7 +297,7 @@ public class JavaTextContainer extends TextContainer { int lastIndex = 0; for (Token t : tokens) { - int tokenStart = text.indexOf(t.text, lastIndex); // find actual index in line + int tokenStart = t.start - this.start; // relative position in line if (tokenStart > lastIndex) { // append the text before the token (spaces, punctuation) builder.append(text, lastIndex, tokenStart);