diff --git a/Ghidra/Debug/Debugger-rmi-trace/src/main/help/help/topics/TraceRmiLauncherServicePlugin/TraceRmiLauncherServicePlugin.html b/Ghidra/Debug/Debugger-rmi-trace/src/main/help/help/topics/TraceRmiLauncherServicePlugin/TraceRmiLauncherServicePlugin.html index 484f746526..2d53e46cfd 100644 --- a/Ghidra/Debug/Debugger-rmi-trace/src/main/help/help/topics/TraceRmiLauncherServicePlugin/TraceRmiLauncherServicePlugin.html +++ b/Ghidra/Debug/Debugger-rmi-trace/src/main/help/help/topics/TraceRmiLauncherServicePlugin/TraceRmiLauncherServicePlugin.html @@ -90,6 +90,21 @@ selected, then this selects nothing, so that pressing the keystroke twice is effectively "Select None."

+

Increase Font Size

+ +

This is accessed using the local drop-down menu or the key sequence CTRL-SHIFT-PLUS. + It increases the font size for this terminal.

+ +

Decrease Font Size

+ +

This is accessed using the local drop-down menu or the key sequence CTRL-MINUS. It + decreases the font size for this terminal.

+ +

Reset Font Size

+ +

This is accessed using the local drop-down menu or the key sequence CTRL-0. It resets + the font size for this terminal according to the theme's configuration'.

+

Terminate

This action is accessed using the local drop-down menu. It will terminate the Terminal's @@ -873,41 +888,45 @@ bdcedit /dbgsettings NET HOSTIP:IP PORT:54321 KEY:1.1.1.1

-

EXDI

- -

Setup for EXDI connections is fairly complicated and difficult to get correct. - The argument string typically should be something like:

- -

The CLSID here should match the CLSID in the exdiConfigData.xml file in the debugger architectural directory. If windbg has been - run using EXDI at some point, there will also be an entry in the System Registry for this CLSID. The InprocServer32 subentry - for this CLSID in the Registry should point to a copy of ExdiGdbSrv.dll, typically the one in the same directory. This DLL - must reside somewhere that the debugger has permission to load from, i.e. not in the WindowsApps directory tree. - The exdiConfigData file should be configured for the target you're using. We heavily recommend using displayCommPackets==yes, - as many of the tasks take considerable time, and this is the only indicator of progress. -

+

EXDI

-

The Kd=Guess parameter causes the underlying engine to scan memory for the kernel's base address, which will probably not - be provided by the gdbstub. (Kd=NtBaseAddr is also a valid option, as is eliminating the parameter, but, currently, we have no - idea how to point the configuration at a correct value. Using this option will cause the load to spin pointlessly.) If you can, - we highly recommend breaking the target near the base address, as the search proceeds down through memory starting at the current - program counter. If the difference between the PC and the base address is large, the loading process will punt before useful - values are detected. If anyone understand how to extend this search (or knows how to set the base address to sidestep the scan), - we would really love some guidance. -

+

Setup for EXDI connections is fairly complicated and difficult to get correct. The argument + string typically should be something like:

+ + + +

The CLSID here should match the CLSID in the exdiConfigData.xml file in the debugger + architectural directory. If windbg has been run using EXDI at some point, there will also be an + entry in the System Registry for this CLSID. The InprocServer32 subentry for this CLSID in the + Registry should point to a copy of ExdiGdbSrv.dll, typically the one in the same directory. + This DLL must reside somewhere that the debugger has permission to load from, i.e. not in the + WindowsApps directory tree. The exdiConfigData file should be configured for the target + you're using. We heavily recommend using displayCommPackets==yes, as many of the tasks + take considerable time, and this is the only indicator of progress.

+ +

The Kd=Guess parameter causes the underlying engine to scan memory for the kernel's + base address, which will probably not be provided by the gdbstub. (Kd=NtBaseAddr is also + a valid option, as is eliminating the parameter, but, currently, we have no idea how to point + the configuration at a correct value. Using this option will cause the load to spin + pointlessly.) If you can, we highly recommend breaking the target near the base address, as the + search proceeds down through memory starting at the current program counter. If the difference + between the PC and the base address is large, the loading process will punt before useful + values are detected. If anyone understand how to extend this search (or knows how to set the + base address to sidestep the scan), we would really love some guidance.

TTD (Time-Travel Debugging)

diff --git a/Ghidra/Features/Base/data/base.theme.properties b/Ghidra/Features/Base/data/base.theme.properties index 05254d0baf..7742023e5b 100644 --- a/Ghidra/Features/Base/data/base.theme.properties +++ b/Ghidra/Features/Base/data/base.theme.properties @@ -127,6 +127,15 @@ color.fg.plugin.terminal.bright.blue = rgb(88,51,255) color.fg.plugin.terminal.bright.magenta = rgb(249,53,248) color.fg.plugin.terminal.bright.cyan = rgb(20,240,240) color.fg.plugin.terminal.bright.white = rgb(233,235,235) +// Just the normals, since normal is bold and dim is plain weight +color.fg.plugin.terminal.dim.black = rgb(0,0,0) +color.fg.plugin.terminal.dim.red = rgb(194,54,33) +color.fg.plugin.terminal.dim.green = rgb(37,188,36) +color.fg.plugin.terminal.dim.yellow = rgb(173,173,39) +color.fg.plugin.terminal.dim.blue = rgb(73,46,255) +color.fg.plugin.terminal.dim.magenta = rgb(211,56,211) +color.fg.plugin.terminal.dim.cyan = rgb(51,187,200) +color.fg.plugin.terminal.dim.white = rgb(203,204,205) color.bg.plugin.locationreferences.highlight = color.palette.lightcornflowerblue @@ -183,7 +192,15 @@ font.plugin.tabs = sansserif-plain-11 font.plugin.tabs.list = sansserif-bold-9 font.plugin.tips = dialog-plain-12 font.plugin.tips.label = font.plugin.tips[bold] -font.plugin.terminal = font.monospaced +font.plugin.terminal = font.monospaced[bold] +font.plugin.terminal.italic = font.plugin.terminal[italic] +font.plugin.terminal.fraktur = font.plugin.terminal +font.plugin.terminal.bright = font.plugin.terminal[bold] +font.plugin.terminal.bright.italic = font.plugin.terminal.bright[italic] +font.plugin.terminal.bright.fraktur = font.plugin.terminal.bright +font.plugin.terminal.dim = font.plugin.terminal[plain] +font.plugin.terminal.dim.italic = font.plugin.terminal.dim[italic] +font.plugin.terminal.dim.fraktur = font.plugin.terminal.dim font.plugin.terminal.completion.list = dialog-plain-12 font.plugin.window.location = font.monospaced[40] diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/terminal/TerminalLayout.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/terminal/TerminalLayout.java index 7807cfcf16..cfe79a266a 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/terminal/TerminalLayout.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/terminal/TerminalLayout.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -35,8 +35,9 @@ public class TerminalLayout extends SingleRowLayout { protected final VtLine line; protected final TerminalTextField field; - public TerminalLayout(VtLine line, FontMetrics metrics, AnsiColorResolver colors) { - super(TerminalTextField.create(line, metrics, colors)); + public TerminalLayout(VtLine line, FontMetrics metrics, float fontSizeAdjustment, + AnsiColorResolver colors) { + super(TerminalTextField.create(line, metrics, fontSizeAdjustment, colors)); this.line = line; this.field = (TerminalTextField) getField(0); } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/terminal/TerminalLayoutModel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/terminal/TerminalLayoutModel.java index e2da7b9a06..60f076dcc3 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/terminal/TerminalLayoutModel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/terminal/TerminalLayoutModel.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -30,6 +30,7 @@ import docking.widgets.fieldpanel.listener.LayoutModelListener; import docking.widgets.fieldpanel.support.FieldLocation; import docking.widgets.fieldpanel.support.FieldRange; import ghidra.app.plugin.core.terminal.vt.*; +import ghidra.app.plugin.core.terminal.vt.AnsiColorResolver.ReverseVideo; import ghidra.app.plugin.core.terminal.vt.VtCharset.G; import ghidra.util.*; @@ -65,6 +66,7 @@ public class TerminalLayoutModel implements LayoutModel, VtHandler { // Rendering properties protected FontMetrics metrics; + protected float fontSizeAdjustment; protected final AnsiColorResolver colors; protected final ArrayList listeners = new ArrayList<>(); @@ -103,6 +105,7 @@ public class TerminalLayoutModel implements LayoutModel, VtHandler { * @param panel the panel to receive commands from the model's VT/ANSI parser * @param charset the charset for decoding bytes to characters * @param metrics font metrics for the monospaced terminal font + * @param fontSizeAdjustment the font size adjustment * @param colors a resolver for ANSI colors */ public TerminalLayoutModel(TerminalPanel panel, Charset charset, FontMetrics metrics, @@ -202,7 +205,7 @@ public class TerminalLayoutModel implements LayoutModel, VtHandler { } protected TerminalLayout newLayout(VtLine line) { - return new TerminalLayout(line, metrics, colors); + return new TerminalLayout(line, metrics, fontSizeAdjustment, colors); } protected void buildLayouts() { @@ -371,7 +374,7 @@ public class TerminalLayoutModel implements LayoutModel, VtHandler { } @Override - public void handleReverseVideo(boolean reverse) { + public void handleReverseVideo(ReverseVideo reverse) { buffer.setAttributes(buffer.getAttributes().reverseVideo(reverse)); } @@ -412,7 +415,7 @@ public class TerminalLayoutModel implements LayoutModel, VtHandler { @Override public void handleAutoWrapMode(boolean en) { - System.err.println("TODO: handleAutoWrapMode: " + en); + Msg.trace(this, "TODO: handleAutoWrapMode: " + en); } @Override @@ -641,7 +644,9 @@ public class TerminalLayoutModel implements LayoutModel, VtHandler { } } - public void setFontMetrics(FontMetrics metrics2) { + public void setFontMetrics(FontMetrics metrics, float fontSizeAdjustment) { + this.metrics = metrics; + this.fontSizeAdjustment = fontSizeAdjustment; layouts.clear(); layoutCache.clear(); buildLayouts(); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/terminal/TerminalPanel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/terminal/TerminalPanel.java index 1cdfee0c9a..9c591b8c76 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/terminal/TerminalPanel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/terminal/TerminalPanel.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -33,8 +33,7 @@ import docking.widgets.fieldpanel.field.Field; import docking.widgets.fieldpanel.listener.*; import docking.widgets.fieldpanel.support.*; import docking.widgets.indexedscrollpane.IndexedScrollPane; -import generic.theme.GColor; -import generic.theme.Gui; +import generic.theme.*; import ghidra.app.plugin.core.terminal.TerminalFinder.RegexTerminalFinder; import ghidra.app.plugin.core.terminal.TerminalFinder.TextTerminalFinder; import ghidra.app.plugin.core.terminal.vt.*; @@ -56,10 +55,30 @@ import ghidra.util.Msg; * most sense to declare the various {@link GColor}s here. */ public class TerminalPanel extends JPanel implements FieldLocationListener, FieldSelectionListener, - LayoutListener, AnsiColorResolver { + LayoutListener, AnsiColorResolver, ThemeListener { protected static final int MAX_TITLE_STACK_SIZE = 20; protected static final String DEFAULT_FONT_ID = "font.plugin.terminal"; + protected static final String DEFAULT_FRAKTUR_FONT_ID = "font.plugin.terminal.fraktur"; + protected static final String DEFAULT_ITALIC_FONT_ID = "font.plugin.terminal.italic"; + protected static final String DIM_FONT_ID = "font.plugin.terminal.dim"; + protected static final String DIM_FRAKTUR_FONT_ID = "font.plugin.terminal.dim.fraktur"; + protected static final String DIM_ITALIC_FONT_ID = "font.plugin.terminal.dim.italic"; + protected static final String BRIGHT_FONT_ID = "font.plugin.terminal.bright"; + protected static final String BRIGHT_FRAKTUR_FONT_ID = "font.plugin.terminal.bright.fraktur"; + protected static final String BRIGHT_ITALIC_FONT_ID = "font.plugin.terminal.bright.italic"; + + protected static final Set ALL_FONT_IDS = Set.of( + DEFAULT_FONT_ID, + DEFAULT_FRAKTUR_FONT_ID, + DEFAULT_ITALIC_FONT_ID, + DIM_FONT_ID, + DIM_FRAKTUR_FONT_ID, + DIM_ITALIC_FONT_ID, + BRIGHT_FONT_ID, + BRIGHT_FRAKTUR_FONT_ID, + BRIGHT_ITALIC_FONT_ID); + protected static final GColor COLOR_BACKGROUND = new GColor("color.bg.plugin.terminal"); protected static final GColor COLOR_FOREGROUND = new GColor("color.fg.plugin.terminal"); protected static final GColor COLOR_CURSOR_FOCUSED = @@ -84,6 +103,7 @@ public class TerminalPanel extends JPanel implements FieldLocationListener, Fiel new GColor("color.fg.plugin.terminal.normal.cyan"); protected static final GColor COLOR_7_WHITE = new GColor("color.fg.plugin.terminal.normal.white"); + protected static final GColor COLOR_0_BRIGHT_BLACK = new GColor("color.fg.plugin.terminal.bright.black"); protected static final GColor COLOR_1_BRIGHT_RED = @@ -101,6 +121,23 @@ public class TerminalPanel extends JPanel implements FieldLocationListener, Fiel protected static final GColor COLOR_7_BRIGHT_WHITE = new GColor("color.fg.plugin.terminal.bright.white"); + protected static final GColor COLOR_0_DIM_BLACK = + new GColor("color.fg.plugin.terminal.dim.black"); + protected static final GColor COLOR_1_DIM_RED = + new GColor("color.fg.plugin.terminal.dim.red"); + protected static final GColor COLOR_2_DIM_GREEN = + new GColor("color.fg.plugin.terminal.dim.green"); + protected static final GColor COLOR_3_DIM_YELLOW = + new GColor("color.fg.plugin.terminal.dim.yellow"); + protected static final GColor COLOR_4_DIM_BLUE = + new GColor("color.fg.plugin.terminal.dim.blue"); + protected static final GColor COLOR_5_DIM_MAGENTA = + new GColor("color.fg.plugin.terminal.dim.magenta"); + protected static final GColor COLOR_6_DIM_CYAN = + new GColor("color.fg.plugin.terminal.dim.cyan"); + protected static final GColor COLOR_7_DIM_WHITE = + new GColor("color.fg.plugin.terminal.dim.white"); + protected static final int[] CUBE_STEPS = { 0, 95, 135, 175, 215, 255 }; @@ -129,6 +166,7 @@ public class TerminalPanel extends JPanel implements FieldLocationListener, Fiel } } + protected float fontSizeAdjustment = 0; protected FontMetrics metrics; protected final TerminalLayoutModel model; protected final TerminalFieldPanel fieldPanel; @@ -153,6 +191,7 @@ public class TerminalPanel extends JPanel implements FieldLocationListener, Fiel this.provider = provider; clipboardProvider = new TerminalClipboardProvider(provider); Gui.registerFont(this, DEFAULT_FONT_ID); + Gui.addThemeListener(this); this.metrics = getFontMetrics(getFont()); this.model = new TerminalLayoutModel(this, charset, metrics, this); this.fieldPanel = new TerminalFieldPanel(model); @@ -346,13 +385,57 @@ public class TerminalPanel extends JPanel implements FieldLocationListener, Fiel } } + @Override + public void themeChanged(ThemeEvent event) { + if (event.isLookAndFeelChanged()) { + setFont(Gui.getFont(DEFAULT_FONT_ID)); + } + if (event.isFontChanged(DEFAULT_FONT_ID)) { + setFont(Gui.getFont(DEFAULT_FONT_ID)); + } + else if (ALL_FONT_IDS.stream().anyMatch(event::isFontChanged)) { + if (model != null) { + model.modelChanged(); + } + } + } + + protected void updateFontMetrics() { + Font font = getFont(); + float size = font.getSize2D(); + fontSizeAdjustment = Math.max(-size + 1, fontSizeAdjustment); + font = font.deriveFont(size + fontSizeAdjustment); + metrics = getFontMetrics(font); + if (model != null) { + model.setFontMetrics(metrics, fontSizeAdjustment); + } + if (!fixedSize) { + resizeTerminalToWindow(); + } + if (model != null) { + model.modelChanged(); + } + } + @Override public void setFont(Font font) { super.setFont(font); - this.metrics = getFontMetrics(font); - if (model != null) { - model.setFontMetrics(this.metrics); - } + updateFontMetrics(); + } + + protected void increaseFontSize() { + fontSizeAdjustment++; + updateFontMetrics(); + } + + protected void decreaseFontSize() { + fontSizeAdjustment--; + updateFontMetrics(); + } + + protected void resetFontSize() { + fontSizeAdjustment = 0; + updateFontMetrics(); } public TerminalFieldPanel getFieldPanel() { @@ -424,29 +507,42 @@ public class TerminalPanel extends JPanel implements FieldLocationListener, Fiel model.processInput(buffer); } - protected Color resolveDefaultColor(WhichGround ground, boolean reverseVideo) { - if (ground == WhichGround.BACKGROUND) { - if (reverseVideo) { - return COLOR_FOREGROUND; - } - return null; // background is already drawn + protected Color resolveDefaultColor(WhichGround ground, ReverseVideo reverse, + Intensity intensity) { + Color color = switch (reverse) { + case NORMAL -> switch (ground) { + case FOREGROUND -> COLOR_FOREGROUND; + case BACKGROUND -> null; // background is already drawn + }; + case REVERSED -> switch (ground) { + case FOREGROUND -> COLOR_BACKGROUND; + case BACKGROUND -> COLOR_FOREGROUND; + }; + }; + if (color == null) { + return null; } - if (reverseVideo) { - return COLOR_BACKGROUND; - } - return COLOR_FOREGROUND; + return switch (intensity) { + case NORMAL -> color; + case BOLD -> color.brighter(); + case DIM -> color.darker(); + }; } - protected Color resolveStandardColor(AnsiStandardColor standard) { - return switch (standard) { - case BLACK -> COLOR_0_BLACK; - case RED -> COLOR_1_RED; - case GREEN -> COLOR_2_GREEN; - case YELLOW -> COLOR_3_YELLOW; - case BLUE -> COLOR_4_BLUE; - case MAGENTA -> COLOR_5_MAGENTA; - case CYAN -> COLOR_6_CYAN; - case WHITE -> COLOR_7_WHITE; + protected Color resolveStandardColor(AnsiStandardColor standard, Intensity intensity) { + return switch (intensity) { + case BOLD -> resolveIntenseColor(standard.intense); + case DIM -> resolveDimColor(standard.dim); + case NORMAL -> switch (standard) { + case BLACK -> COLOR_0_BLACK; + case RED -> COLOR_1_RED; + case GREEN -> COLOR_2_GREEN; + case YELLOW -> COLOR_3_YELLOW; + case BLUE -> COLOR_4_BLUE; + case MAGENTA -> COLOR_5_MAGENTA; + case CYAN -> COLOR_6_CYAN; + case WHITE -> COLOR_7_WHITE; + }; }; } @@ -463,6 +559,19 @@ public class TerminalPanel extends JPanel implements FieldLocationListener, Fiel }; } + protected Color resolveDimColor(AnsiDimColor intense) { + return switch (intense) { + case BLACK -> COLOR_0_DIM_BLACK; + case RED -> COLOR_1_DIM_RED; + case GREEN -> COLOR_2_DIM_GREEN; + case YELLOW -> COLOR_3_DIM_YELLOW; + case BLUE -> COLOR_4_DIM_BLUE; + case MAGENTA -> COLOR_5_DIM_MAGENTA; + case CYAN -> COLOR_6_DIM_CYAN; + case WHITE -> COLOR_7_DIM_WHITE; + }; + } + protected Color resolve216Color(Ansi216Color cube) { return ColorUtils.getColor(CUBE_STEPS[cube.r()], CUBE_STEPS[cube.g()], CUBE_STEPS[cube.b()]); @@ -478,12 +587,12 @@ public class TerminalPanel extends JPanel implements FieldLocationListener, Fiel @Override public Color resolveColor(AnsiColor color, WhichGround ground, Intensity intensity, - boolean reverseVideo) { + ReverseVideo reverse) { if (color == AnsiDefaultColor.INSTANCE) { - return resolveDefaultColor(ground, reverseVideo); + return resolveDefaultColor(ground, reverse, intensity); } if (color instanceof AnsiStandardColor standard) { - return resolveStandardColor(standard); + return resolveStandardColor(standard, intensity); } if (color instanceof AnsiIntenseColor intense) { return resolveIntenseColor(intense); @@ -560,6 +669,8 @@ public class TerminalPanel extends JPanel implements FieldLocationListener, Fiel } public void dispose() { + Gui.unRegisterFont(this, DEFAULT_FONT_ID); + Gui.removeThemeListener(this); if (this.clipboardService != null) { clipboardService.deRegisterClipboardContentProvider(clipboardProvider); } @@ -663,6 +774,10 @@ public class TerminalPanel extends JPanel implements FieldLocationListener, Fiel } protected void resizeTerminalToWindow() { + if (scroller == null) { + // Some callback during construction + return; + } Rectangle bounds = scroller.getViewportBorderBounds(); int cols = bounds.width / metrics.charWidth('M'); int rows = bounds.height / metrics.getHeight(); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/terminal/TerminalProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/terminal/TerminalProvider.java index 0e6539f8bf..824816bdd8 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/terminal/TerminalProvider.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/terminal/TerminalProvider.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -167,6 +167,9 @@ public class TerminalProvider extends ComponentProviderAdapter { protected DockingAction actionFindPrevious; protected DockingAction actionSelectAll; protected DockingAction actionTerminate; + protected DockingAction actionIncreaseSize; + protected DockingAction actionDecreaseSize; + protected DockingAction actionResetSize; private boolean terminated = false; @@ -262,6 +265,28 @@ public class TerminalProvider extends ComponentProviderAdapter { .helpLocation(new HelpLocation(helpPlugin.getName(), "select_all")) .onAction(this::activatedSelectAll) .buildAndInstallLocal(this); + actionIncreaseSize = new ActionBuilder("Increase Font Size", plugin.getName()) + .menuPath("Increase Font Size") + .menuGroup("View") + .keyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_EQUALS, + InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK)) + .helpLocation(new HelpLocation(helpPlugin.getName(), "increase_font_size")) + .onAction(this::activatedIncreaseFontSize) + .buildAndInstallLocal(this); + actionDecreaseSize = new ActionBuilder("Decrease Font Size", plugin.getName()) + .menuPath("Decrease Font Size") + .menuGroup("View") + .keyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_MINUS, InputEvent.CTRL_DOWN_MASK)) + .helpLocation(new HelpLocation(helpPlugin.getName(), "decrease_font_size")) + .onAction(this::activatedDecreaseFontSize) + .buildAndInstallLocal(this); + actionResetSize = new ActionBuilder("Reset Font Size", plugin.getName()) + .menuPath("Reset Font Size") + .menuGroup("View") + .keyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_0, InputEvent.CTRL_DOWN_MASK)) + .helpLocation(new HelpLocation(helpPlugin.getName(), "decrease_font_size")) + .onAction(this::activatedResetFontSize) + .buildAndInstallLocal(this); } protected void activatedFind(ActionContext ctx) { @@ -329,6 +354,18 @@ public class TerminalProvider extends ComponentProviderAdapter { panel.getFieldPanel().setSelection(sel, EventTrigger.GUI_ACTION); } + protected void activatedIncreaseFontSize(ActionContext ctx) { + panel.increaseFontSize(); + } + + protected void activatedDecreaseFontSize(ActionContext ctx) { + panel.decreaseFontSize(); + } + + protected void activatedResetFontSize(ActionContext ctx) { + panel.resetFontSize(); + } + /** * Check if the given keystroke would activate a local action. * diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/terminal/TerminalTextField.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/terminal/TerminalTextField.java index 47e80a4c96..300e399a5c 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/terminal/TerminalTextField.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/terminal/TerminalTextField.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -51,13 +51,14 @@ public class TerminalTextField implements TextField { * * @param line the line from the {@link VtBuffer} that will be rendered in this field * @param metrics the font metrics + * @param fontSizeAdjustment the font size adjustment * @param colors the color resolver * @return the field */ public static TerminalTextField create(VtLine line, FontMetrics metrics, - AnsiColorResolver colors) { - return new TerminalTextField(0, new TerminalTextFieldElement(line, metrics, colors), - metrics); + float fontSizeAdjustment, AnsiColorResolver colors) { + return new TerminalTextField(0, + new TerminalTextFieldElement(line, metrics, fontSizeAdjustment, colors), metrics); } protected TerminalTextField(int startX, TerminalTextFieldElement element, FontMetrics metrics) { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/terminal/TerminalTextFieldElement.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/terminal/TerminalTextFieldElement.java index 81dada432d..adcf731613 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/terminal/TerminalTextFieldElement.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/terminal/TerminalTextFieldElement.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -22,8 +22,8 @@ import javax.swing.JComponent; import docking.widgets.fieldpanel.field.FieldElement; import docking.widgets.fieldpanel.support.RowColLocation; +import generic.theme.Gui; import ghidra.app.plugin.core.terminal.vt.*; -import ghidra.app.plugin.core.terminal.vt.VtHandler.Intensity; /** * A text field element for rendering a full line of terminal text @@ -41,6 +41,7 @@ public class TerminalTextFieldElement implements FieldElement { protected final VtLine line; protected final FontMetrics metrics; + protected final float fontSizeAdjustment; protected final AnsiColorResolver colors; protected final int em; @@ -50,11 +51,14 @@ public class TerminalTextFieldElement implements FieldElement { * * @param line the line of text from the {@link VtBuffer} * @param metrics the font metrics + * @param fontSizeAdjustment the font size adjustment * @param colors the color resolver */ - public TerminalTextFieldElement(VtLine line, FontMetrics metrics, AnsiColorResolver colors) { + public TerminalTextFieldElement(VtLine line, FontMetrics metrics, float fontSizeAdjustment, + AnsiColorResolver colors) { this.line = line; this.metrics = metrics; + this.fontSizeAdjustment = fontSizeAdjustment; this.colors = colors; this.em = metrics.charWidth('M'); @@ -163,22 +167,34 @@ public class TerminalTextFieldElement implements FieldElement { int height = metrics.getHeight(); int left = x + start * em; int width = em * (end - start); - Font font = metrics.getFont(); Color bg = attrs.resolveBackground(colors); if (bg != null) { g.setColor(bg); g.fillRect(left, descent - height, width, height); } g.setColor(attrs.resolveForeground(colors)); - // NB. I don't really intend to implement blinking. - // TODO: AnsiFont mapping? - if (attrs.intensity() == Intensity.DIM) { - g.setFont(font.deriveFont(Font.PLAIN)); - } - else { - // Normal will use bold font, but standard color - g.setFont(font.deriveFont(Font.BOLD)); - } + // I don't really intend to implement blinking. + // We still use metrics from DEFAULT_FONT_ID + Font font = Gui.getFont(switch (attrs.intensity()) { + case NORMAL -> switch (attrs.font()) { + case NORMAL -> TerminalPanel.DEFAULT_FONT_ID; + case ITALIC -> TerminalPanel.DEFAULT_ITALIC_FONT_ID; + case BLACK_LETTER -> TerminalPanel.DEFAULT_FRAKTUR_FONT_ID; + }; + case BOLD -> switch (attrs.font()) { + case NORMAL -> TerminalPanel.BRIGHT_FONT_ID; + case ITALIC -> TerminalPanel.BRIGHT_ITALIC_FONT_ID; + case BLACK_LETTER -> TerminalPanel.BRIGHT_FRAKTUR_FONT_ID; + }; + case DIM -> switch (attrs.font()) { + case NORMAL -> TerminalPanel.DIM_FONT_ID; + case ITALIC -> TerminalPanel.DIM_ITALIC_FONT_ID; + case BLACK_LETTER -> TerminalPanel.DIM_FRAKTUR_FONT_ID; + }; + }); + font = font.deriveFont(font.getSize2D() + fontSizeAdjustment); + g.setFont(font); + if (!attrs.hidden()) { switch (attrs.underline()) { case DOUBLE: diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/terminal/vt/AnsiColorResolver.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/terminal/vt/AnsiColorResolver.java index e0c667ff6f..0cfecd7dba 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/terminal/vt/AnsiColorResolver.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/terminal/vt/AnsiColorResolver.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -32,6 +32,35 @@ public interface AnsiColorResolver { FOREGROUND, BACKGROUND; } + enum ReverseVideo { + NORMAL { + @Override + AnsiColor fg(AnsiColor fg, AnsiColor bg) { + return fg; + } + + @Override + AnsiColor bg(AnsiColor fg, AnsiColor bg) { + return bg; + } + }, + REVERSED { + @Override + AnsiColor fg(AnsiColor fg, AnsiColor bg) { + return bg; + } + + @Override + AnsiColor bg(AnsiColor fg, AnsiColor bg) { + return fg; + } + }; + + abstract AnsiColor fg(AnsiColor fg, AnsiColor bg); + + abstract AnsiColor bg(AnsiColor fg, AnsiColor bg); + } + /** * Convert a color specification to an AWT color * @@ -39,11 +68,11 @@ public interface AnsiColorResolver { * @param ground identifies the colors use in the foreground or the background * @param intensity gives the intensity of the color, really only used when a basic color is * specified. - * @param reverseVideo identifies whether the foreground and background colors were swapped, - * really only used when the default color is specified. + * @param reverse identifies whether the foreground and background colors were swapped, really + * only used when the default color is specified. * @return the AWT color, or null to not draw (usually in the case of the default background * color) */ Color resolveColor(AnsiColor color, WhichGround ground, Intensity intensity, - boolean reverseVideo); + ReverseVideo reverse); } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/terminal/vt/VtAttributes.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/terminal/vt/VtAttributes.java index 784ad8c197..8a04ad4b25 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/terminal/vt/VtAttributes.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/terminal/vt/VtAttributes.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -17,6 +17,7 @@ package ghidra.app.plugin.core.terminal.vt; import java.awt.Color; +import ghidra.app.plugin.core.terminal.vt.AnsiColorResolver.ReverseVideo; import ghidra.app.plugin.core.terminal.vt.AnsiColorResolver.WhichGround; import ghidra.app.plugin.core.terminal.vt.VtHandler.*; @@ -30,7 +31,7 @@ import ghidra.app.plugin.core.terminal.vt.VtHandler.*; * in the buffer. */ public record VtAttributes(AnsiColor fg, AnsiColor bg, Intensity intensity, - AnsiFont font, Underline underline, Blink blink, boolean reverseVideo, boolean hidden, + AnsiFont font, Underline underline, Blink blink, ReverseVideo reverse, boolean hidden, boolean strikeThrough, boolean proportionalSpacing) { /** @@ -38,8 +39,8 @@ public record VtAttributes(AnsiColor fg, AnsiColor bg, Intensity intensity, */ public static final VtAttributes DEFAULTS = new VtAttributes(AnsiDefaultColor.INSTANCE, AnsiDefaultColor.INSTANCE, - Intensity.NORMAL, AnsiFont.NORMAL, Underline.NONE, Blink.NONE, false, false, false, - false); + Intensity.NORMAL, AnsiFont.NORMAL, Underline.NONE, Blink.NONE, ReverseVideo.NORMAL, + false, false, false); /** * Create a copy of this record with the foreground color replaced @@ -48,8 +49,8 @@ public record VtAttributes(AnsiColor fg, AnsiColor bg, Intensity intensity, * @return the new record */ public VtAttributes fg(AnsiColor fg) { - return new VtAttributes(fg, bg, intensity, font, underline, blink, reverseVideo, - hidden, strikeThrough, proportionalSpacing); + return new VtAttributes(fg, bg, intensity, font, underline, blink, reverse, hidden, + strikeThrough, proportionalSpacing); } /** @@ -59,8 +60,8 @@ public record VtAttributes(AnsiColor fg, AnsiColor bg, Intensity intensity, * @return the new record */ public VtAttributes bg(AnsiColor bg) { - return new VtAttributes(fg, bg, intensity, font, underline, blink, reverseVideo, - hidden, strikeThrough, proportionalSpacing); + return new VtAttributes(fg, bg, intensity, font, underline, blink, reverse, hidden, + strikeThrough, proportionalSpacing); } /** @@ -70,8 +71,8 @@ public record VtAttributes(AnsiColor fg, AnsiColor bg, Intensity intensity, * @return the new record */ public VtAttributes intensity(Intensity intensity) { - return new VtAttributes(fg, bg, intensity, font, underline, blink, reverseVideo, - hidden, strikeThrough, proportionalSpacing); + return new VtAttributes(fg, bg, intensity, font, underline, blink, reverse, hidden, + strikeThrough, proportionalSpacing); } /** @@ -81,8 +82,8 @@ public record VtAttributes(AnsiColor fg, AnsiColor bg, Intensity intensity, * @return the new record */ public VtAttributes font(AnsiFont font) { - return new VtAttributes(fg, bg, intensity, font, underline, blink, reverseVideo, - hidden, strikeThrough, proportionalSpacing); + return new VtAttributes(fg, bg, intensity, font, underline, blink, reverse, hidden, + strikeThrough, proportionalSpacing); } /** @@ -92,8 +93,8 @@ public record VtAttributes(AnsiColor fg, AnsiColor bg, Intensity intensity, * @return the new record */ public VtAttributes underline(Underline underline) { - return new VtAttributes(fg, bg, intensity, font, underline, blink, reverseVideo, - hidden, strikeThrough, proportionalSpacing); + return new VtAttributes(fg, bg, intensity, font, underline, blink, reverse, hidden, + strikeThrough, proportionalSpacing); } /** @@ -103,19 +104,19 @@ public record VtAttributes(AnsiColor fg, AnsiColor bg, Intensity intensity, * @return the new record */ public VtAttributes blink(Blink blink) { - return new VtAttributes(fg, bg, intensity, font, underline, blink, reverseVideo, - hidden, strikeThrough, proportionalSpacing); + return new VtAttributes(fg, bg, intensity, font, underline, blink, reverse, hidden, + strikeThrough, proportionalSpacing); } /** * Create a copy of this record with the reverse-video replaced * - * @param reverseVideo the new reverse-video + * @param reverse the new reverse-video * @return the new record */ - public VtAttributes reverseVideo(boolean reverseVideo) { - return new VtAttributes(fg, bg, intensity, font, underline, blink, reverseVideo, - hidden, strikeThrough, proportionalSpacing); + public VtAttributes reverseVideo(ReverseVideo reverse) { + return new VtAttributes(fg, bg, intensity, font, underline, blink, reverse, hidden, + strikeThrough, proportionalSpacing); } /** @@ -125,8 +126,8 @@ public record VtAttributes(AnsiColor fg, AnsiColor bg, Intensity intensity, * @return the new record */ public VtAttributes hidden(boolean hidden) { - return new VtAttributes(fg, bg, intensity, font, underline, blink, reverseVideo, - hidden, strikeThrough, proportionalSpacing); + return new VtAttributes(fg, bg, intensity, font, underline, blink, reverse, hidden, + strikeThrough, proportionalSpacing); } /** @@ -136,8 +137,8 @@ public record VtAttributes(AnsiColor fg, AnsiColor bg, Intensity intensity, * @return the new record */ public VtAttributes strikeThrough(boolean strikeThrough) { - return new VtAttributes(fg, bg, intensity, font, underline, blink, reverseVideo, - hidden, strikeThrough, proportionalSpacing); + return new VtAttributes(fg, bg, intensity, font, underline, blink, reverse, hidden, + strikeThrough, proportionalSpacing); } /** @@ -147,8 +148,8 @@ public record VtAttributes(AnsiColor fg, AnsiColor bg, Intensity intensity, * @return the new record */ public VtAttributes proportionalSpacing(boolean proportionalSpacing) { - return new VtAttributes(fg, bg, intensity, font, underline, blink, reverseVideo, - hidden, strikeThrough, proportionalSpacing); + return new VtAttributes(fg, bg, intensity, font, underline, blink, reverse, hidden, + strikeThrough, proportionalSpacing); } /** @@ -158,8 +159,7 @@ public record VtAttributes(AnsiColor fg, AnsiColor bg, Intensity intensity, * @return the color */ public Color resolveForeground(AnsiColorResolver colors) { - return colors.resolveColor(reverseVideo ? bg : fg, WhichGround.FOREGROUND, intensity, - reverseVideo); + return colors.resolveColor(reverse.fg(fg, bg), WhichGround.FOREGROUND, intensity, reverse); } /** @@ -169,7 +169,7 @@ public record VtAttributes(AnsiColor fg, AnsiColor bg, Intensity intensity, * @return the color, or null to not paint the background */ public Color resolveBackground(AnsiColorResolver colors) { - return colors.resolveColor(reverseVideo ? fg : bg, WhichGround.BACKGROUND, Intensity.NORMAL, - reverseVideo); + return colors.resolveColor(reverse.bg(fg, bg), WhichGround.BACKGROUND, Intensity.NORMAL, + reverse); } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/terminal/vt/VtHandler.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/terminal/vt/VtHandler.java index f370d4a3a2..570a486c13 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/terminal/vt/VtHandler.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/terminal/vt/VtHandler.java @@ -23,6 +23,7 @@ import java.util.PrimitiveIterator.OfInt; import java.util.regex.Matcher; import java.util.regex.Pattern; +import ghidra.app.plugin.core.terminal.vt.AnsiColorResolver.ReverseVideo; import ghidra.util.Msg; /** @@ -171,43 +172,51 @@ public interface VtHandler { * Usually the darkest black available. Implementations may select a color softer on the * eyes, depending on use. For foreground, this should likely be true black (0,0,0). */ - BLACK, + BLACK(AnsiIntenseColor.BLACK, AnsiDimColor.BLACK), /** * A color whose hue is clearly red. */ - RED, + RED(AnsiIntenseColor.RED, AnsiDimColor.RED), /** * A color whose hue is clearly green. */ - GREEN, + GREEN(AnsiIntenseColor.GREEN, AnsiDimColor.GREEN), /** * A color whose hue is clearly yellow. */ - YELLOW, + YELLOW(AnsiIntenseColor.YELLOW, AnsiDimColor.YELLOW), /** * A color whose hue is clearly blue. For palettes made to display on a dark (but not black) * background, a hue tinted toward cyan is recommended. */ - BLUE, + BLUE(AnsiIntenseColor.BLUE, AnsiDimColor.BLUE), /** * A color whose hue is clearly magenta or purple. For palettes made to display on a dark * (but not black) background, a hue tinted toward red is recommended. */ - MAGENTA, + MAGENTA(AnsiIntenseColor.MAGENTA, AnsiDimColor.MAGENTA), /** * A color whose hue is clearly cyan. */ - CYAN, + CYAN(AnsiIntenseColor.CYAN, AnsiDimColor.CYAN), /** * A relatively bright white, sparing the brightest for intense white. */ - WHITE; + WHITE(AnsiIntenseColor.WHITE, AnsiDimColor.WHITE); /** * An unmodifiable list giving all the standard colors */ public static final List ALL = List.of(AnsiStandardColor.values()); + public final AnsiIntenseColor intense; + public final AnsiDimColor dim; + + private AnsiStandardColor(AnsiIntenseColor intense, AnsiDimColor dim) { + this.intense = intense; + this.dim = dim; + } + /** * Get the standard color for the given numerical code * @@ -282,14 +291,69 @@ public interface VtHandler { } } + /** + * One of the eight ANSI dim colors + */ + public enum AnsiDimColor implements AnsiColor { + /** + * A relatively dark grey, but not true black. + */ + BLACK, + /** + * See {@link AnsiStandardColor#RED}, but darker. + */ + RED, + /** + * See {@link AnsiStandardColor#GREEN}, but darker. + */ + GREEN, + /** + * See {@link AnsiStandardColor#YELLOW}, but darker. + */ + YELLOW, + /** + * See {@link AnsiStandardColor#BLUE}, but darker. + */ + BLUE, + /** + * See {@link AnsiStandardColor#MAGENTA}, but darker. + */ + MAGENTA, + /** + * See {@link AnsiStandardColor#CYAN}, but darker. + */ + CYAN, + /** + * Usually grey. + */ + WHITE; + + /** + * An unmodifiable list giving all the dim colors + */ + public static final List ALL = List.of(AnsiDimColor.values()); + + /** + * Get the dim color for the given numerical code + * + *

+ * For example, the sequence {@code CSI [ 34 m} would use code 4 (blue). + * + * @param code the code + * @return the color + */ + public static AnsiDimColor get(int code) { + return ALL.get(code); + } + } + /** * For 8-bit colors, one of the 216 colors from the RGB cube * *

* The r, g, and b fields give the "step" number from 0 to 5, dimmest to brightest. */ - public record Ansi216Color(int r, int g, int b) implements AnsiColor { - } + public record Ansi216Color(int r, int g, int b) implements AnsiColor {} /** * For 8-bit colors, one of the 24 grays @@ -298,8 +362,7 @@ public interface VtHandler { * The v field is a value from 0 to 23, 0 being the dimmest, but not true black, and 23 being * the brightest, but not true white. */ - public record AnsiGrayscaleColor(int v) implements AnsiColor { - } + public record AnsiGrayscaleColor(int v) implements AnsiColor {} /** * A 24-bit color @@ -307,8 +370,7 @@ public interface VtHandler { *

* The r, g, and b fields are values from 0 to 255 dimmest to brightest. */ - public record Ansi24BitColor(int r, int g, int b) implements AnsiColor { - } + public record Ansi24BitColor(int r, int g, int b) implements AnsiColor {} /** * Modifies the intensity of the character either by color or by font weight. @@ -1202,7 +1264,7 @@ public interface VtHandler { handleBlink(Blink.FAST); return; case 7: - handleReverseVideo(true); + handleReverseVideo(ReverseVideo.REVERSED); return; case 8: handleHidden(true); @@ -1232,7 +1294,7 @@ public interface VtHandler { handleProportionalSpacing(true); return; case 27: - handleReverseVideo(false); + handleReverseVideo(ReverseVideo.NORMAL); return; case 28: handleHidden(false); @@ -1345,9 +1407,9 @@ public interface VtHandler { * "default background," care must be taken to ensure the foreground is still painted in * reversed mode. * - * @param reverse true to reverse, false otherwise + * @param reverse the reverse video mode */ - void handleReverseVideo(boolean reverse); + void handleReverseVideo(ReverseVideo reverse); /** * Handle toggling of the hidden attribute 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 952c61cb73..05e7e6d843 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 @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -63,6 +63,8 @@ public class TerminalProviderTest extends AbstractGhidraHeadedDebuggerTest { terminalService = addPlugin(tool, TerminalPlugin.class); clipboardService = addPlugin(tool, ClipboardPlugin.class); + env.showFrontEndTool(); + PtyFactory factory = PtyFactory.local(); try (Pty pty = factory.openpty()) { Map env = new HashMap<>(System.getenv());