From fb9cbdf7ed1d85d0837b1cf78b2d5dcb37883036 Mon Sep 17 00:00:00 2001 From: Dan <46821332+nsadeveloper789@users.noreply.github.com> Date: Fri, 19 Jan 2024 15:46:59 -0500 Subject: [PATCH] GP-4223: Fix case-insenstive search in Terminal window. --- .../plugin/core/terminal/TerminalFinder.java | 42 ++++++++--- .../core/terminal/TerminalProviderTest.java | 72 ++++++++++++++++++- 2 files changed, 103 insertions(+), 11 deletions(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/terminal/TerminalFinder.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/terminal/TerminalFinder.java index e3cc65d7b2..971defc96f 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/terminal/TerminalFinder.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/terminal/TerminalFinder.java @@ -73,11 +73,7 @@ public abstract class TerminalFinder { this.wholeWord = options.contains(FindOptions.WHOLE_WORD); } - protected void lowerBuf(StringBuilder sb) { - for (int i = 0; i < sb.length(); i++) { - sb.setCharAt(i, Character.toLowerCase(sb.charAt(i))); - } - } + protected abstract void caseBuf(StringBuilder sb); protected boolean isWholeWord(int i, String match) { if (i > 0 && VtLine.isWordChar(sb.charAt(i - 1))) { @@ -113,9 +109,7 @@ public abstract class TerminalFinder { VtLine line = layout.line; sb.delete(0, sb.length()); line.gatherText(sb, 0, line.length()); - if (!caseSensitive) { - lowerBuf(sb); - } + caseBuf(sb); int s; if (index.equals(cur.getIndex())) { s = cur.getCol(); @@ -166,7 +160,12 @@ public abstract class TerminalFinder { if (text.isEmpty()) { throw new IllegalArgumentException("Empty text"); } - this.text = text; + if (!caseSensitive) { + this.text = text.toLowerCase(); + } + else { + this.text = text; + } } @Override @@ -188,6 +187,19 @@ public abstract class TerminalFinder { } return null; } + + protected void lowerBuf(StringBuilder sb) { + for (int i = 0; i < sb.length(); i++) { + sb.setCharAt(i, Character.toLowerCase(sb.charAt(i))); + } + } + + @Override + protected void caseBuf(StringBuilder sb) { + if (!caseSensitive) { + lowerBuf(sb); + } + } } /** @@ -205,7 +217,12 @@ public abstract class TerminalFinder { if (pattern.isEmpty()) { throw new IllegalArgumentException("Empty pattern"); } - this.pattern = Pattern.compile(pattern); + if (!caseSensitive) { + this.pattern = Pattern.compile(pattern, Pattern.CASE_INSENSITIVE); + } + else { + this.pattern = Pattern.compile(pattern); + } } @Override @@ -246,5 +263,10 @@ public abstract class TerminalFinder { new FieldLocation(index, 0, 0, lastStart), new FieldLocation(index, 0, 0, lastEnd)); } + + @Override + protected void caseBuf(StringBuilder sb) { + // Nothing. Pattern handles it. + } } } diff --git a/Ghidra/Test/IntegrationTest/src/test.slow/java/ghidra/app/plugin/core/terminal/TerminalProviderTest.java b/Ghidra/Test/IntegrationTest/src/test.slow/java/ghidra/app/plugin/core/terminal/TerminalProviderTest.java index a9b3d4f49c..14f6a15ab0 100644 --- a/Ghidra/Test/IntegrationTest/src/test.slow/java/ghidra/app/plugin/core/terminal/TerminalProviderTest.java +++ b/Ghidra/Test/IntegrationTest/src/test.slow/java/ghidra/app/plugin/core/terminal/TerminalProviderTest.java @@ -150,7 +150,7 @@ public class TerminalProviderTest extends AbstractGhidraHeadedDebuggerTest { @Test @SuppressWarnings("resource") - public void testFindSimple() throws Exception { + public void testFindText() throws Exception { terminalService = addPlugin(tool, TerminalPlugin.class); try (DefaultTerminal term = (DefaultTerminal) terminalService @@ -180,6 +180,38 @@ public class TerminalProviderTest extends AbstractGhidraHeadedDebuggerTest { } } + @Test + @SuppressWarnings("resource") + public void testFindTextCaps() throws Exception { + terminalService = addPlugin(tool, TerminalPlugin.class); + + try (DefaultTerminal term = (DefaultTerminal) terminalService + .createNullTerminal(Charset.forName("UTF-8"), buf -> { + })) { + term.setFixedSize(80, 25); + term.injectDisplayOutput(TEST_CONTENTS); + + term.provider.findDialog.txtFind.setText("TERM"); + + performAction(term.provider.actionFindNext, false); + waitForPass(() -> assertSingleSelection(0, 0, 4, + term.provider.panel.fieldPanel.getSelection())); + + performAction(term.provider.actionFindNext, false); + waitForPass(() -> assertSingleSelection(0, 5, 9, + term.provider.panel.fieldPanel.getSelection())); + + performAction(term.provider.actionFindNext, false); + waitForPass(() -> assertSingleSelection(1, 2, 6, + term.provider.panel.fieldPanel.getSelection())); + + performAction(term.provider.actionFindNext, false); + OkDialog dialog = waitForInfoDialog(); + assertEquals("String not found", dialog.getMessage()); + dialog.close(); + } + } + @Test @SuppressWarnings("resource") public void testFindCaseSensitive() throws Exception { @@ -308,6 +340,44 @@ public class TerminalProviderTest extends AbstractGhidraHeadedDebuggerTest { } } + @Test + @SuppressWarnings("resource") + public void testFindRegexCaps() throws Exception { + terminalService = addPlugin(tool, TerminalPlugin.class); + + try (DefaultTerminal term = (DefaultTerminal) terminalService + .createNullTerminal(Charset.forName("UTF-8"), buf -> { + })) { + term.setFixedSize(80, 25); + term.injectDisplayOutput(TEST_CONTENTS); + + term.provider.findDialog.txtFind.setText("o?TERM"); + term.provider.findDialog.cbRegex.setSelected(true); + + performAction(term.provider.actionFindNext, false); + waitForPass(() -> assertSingleSelection(0, 0, 4, + term.provider.panel.fieldPanel.getSelection())); + + performAction(term.provider.actionFindNext, false); + waitForPass(() -> assertSingleSelection(0, 5, 9, + term.provider.panel.fieldPanel.getSelection())); + + performAction(term.provider.actionFindNext, false); + waitForPass(() -> assertSingleSelection(1, 1, 6, + term.provider.panel.fieldPanel.getSelection())); + + // NB. the o is optional, so it finds a subrange of the previous result + performAction(term.provider.actionFindNext, false); + waitForPass(() -> assertSingleSelection(1, 2, 6, + term.provider.panel.fieldPanel.getSelection())); + + performAction(term.provider.actionFindNext, false); + OkDialog dialog = waitForInfoDialog(); + assertEquals("String not found", dialog.getMessage()); + dialog.close(); + } + } + @Test @SuppressWarnings("resource") public void testFindPrevious() throws Exception {