mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 17:59:46 +02:00
Merge remote-tracking branch 'origin/GP-5003_improveTerminalFonts--SQUASHED'
This commit is contained in:
commit
473c16f1cb
12 changed files with 456 additions and 152 deletions
|
@ -90,6 +90,21 @@
|
||||||
selected, then this selects nothing, so that pressing the keystroke twice is effectively
|
selected, then this selects nothing, so that pressing the keystroke twice is effectively
|
||||||
"Select None."</P>
|
"Select None."</P>
|
||||||
|
|
||||||
|
<H3><A name="increase_font_size"></A>Increase Font Size</H3>
|
||||||
|
|
||||||
|
<P>This is accessed using the local drop-down menu or the key sequence <B>CTRL-SHIFT-PLUS</B>.
|
||||||
|
It increases the font size for this terminal.</P>
|
||||||
|
|
||||||
|
<H3><A name="decrease_font_size"></A>Decrease Font Size</H3>
|
||||||
|
|
||||||
|
<P>This is accessed using the local drop-down menu or the key sequence <B>CTRL-MINUS</B>. It
|
||||||
|
decreases the font size for this terminal.</P>
|
||||||
|
|
||||||
|
<H3><A name="reset_font_size"></A>Reset Font Size</H3>
|
||||||
|
|
||||||
|
<P>This is accessed using the local drop-down menu or the key sequence <B>CTRL-0</B>. It resets
|
||||||
|
the font size for this terminal according to the theme's configuration'.</P>
|
||||||
|
|
||||||
<H3><A name="terminate"></A>Terminate</H3>
|
<H3><A name="terminate"></A>Terminate</H3>
|
||||||
|
|
||||||
<P>This action is accessed using the local drop-down menu. It will terminate the Terminal's
|
<P>This action is accessed using the local drop-down menu. It will terminate the Terminal's
|
||||||
|
@ -873,18 +888,19 @@ bdcedit /dbgsettings NET HOSTIP:IP PORT:54321 KEY:1.1.1.1
|
||||||
|
|
||||||
<UL>
|
<UL>
|
||||||
<LI><B>Type</B>: The type of kernel connection, either "Remote", "Local", or "EXDI".
|
<LI><B>Type</B>: The type of kernel connection, either "Remote", "Local", or "EXDI".
|
||||||
"Remote", the most common type, indicates two-machine debugging over various
|
"Remote", the most common type, indicates two-machine debugging over various possible
|
||||||
possible connection media, e.g. Ethernet, serial, USB, etc. "Local" is used for limited
|
connection media, e.g. Ethernet, serial, USB, etc. "Local" is used for limited introspection
|
||||||
introspection into the target on which the debugger is running. "EXDI" is arguably
|
into the target on which the debugger is running. "EXDI" is arguably the most exotic type -
|
||||||
the most exotic type - it essentially simulates the normal "Remote" connection using
|
it essentially simulates the normal "Remote" connection using the gdb Remote Serial Protocol.
|
||||||
the gdb Remote Serial Protocol. It can be used when connecting to gdbstubs in
|
It can be used when connecting to gdbstubs in platforms, such as QEMU, VMWare, Trace32,
|
||||||
platforms, such as QEMU, VMWare, Trace32, etc.</LI>
|
etc.</LI>
|
||||||
</UL>
|
</UL>
|
||||||
|
|
||||||
<H4>EXDI</H4>
|
<H4>EXDI</H4>
|
||||||
|
|
||||||
<P>Setup for EXDI connections is fairly complicated and difficult to get correct.
|
<P>Setup for EXDI connections is fairly complicated and difficult to get correct. The argument
|
||||||
The argument string typically should be something like:</P>
|
string typically should be something like:</P>
|
||||||
|
|
||||||
<UL style='list-style-type: none'>
|
<UL style='list-style-type: none'>
|
||||||
<LI>
|
<LI>
|
||||||
<PRE>
|
<PRE>
|
||||||
|
@ -892,22 +908,25 @@ bdcedit /dbgsettings NET HOSTIP:IP PORT:54321 KEY:1.1.1.1
|
||||||
</PRE>
|
</PRE>
|
||||||
</LI>
|
</LI>
|
||||||
</UL>
|
</UL>
|
||||||
<P>The CLSID here should match the CLSID in the <B>exdiConfigData.xml</B> 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 <B>exdiConfigData</B> file should be configured for the target you're using. We heavily recommend using <B>displayCommPackets==yes</B>,
|
|
||||||
as many of the tasks take considerable time, and this is the only indicator of progress.
|
|
||||||
</P>
|
|
||||||
|
|
||||||
<P>The <B>Kd=Guess</B> parameter causes the underlying engine to scan memory for the kernel's base address, which will probably not
|
<P>The CLSID here should match the CLSID in the <B>exdiConfigData.xml</B> file in the debugger
|
||||||
be provided by the gdbstub. (<B>Kd=NtBaseAddr</B> is also a valid option, as is eliminating the parameter, but, currently, we have no
|
architectural directory. If windbg has been run using EXDI at some point, there will also be an
|
||||||
idea how to point the configuration at a correct value. Using this option will cause the load to spin pointlessly.) If you can,
|
entry in the System Registry for this CLSID. The InprocServer32 subentry for this CLSID in the
|
||||||
we highly recommend breaking the target near the base address, as the search proceeds down through memory starting at the current
|
Registry should point to a copy of ExdiGdbSrv.dll, typically the one in the same directory.
|
||||||
program counter. If the difference between the PC and the base address is large, the loading process will punt before useful
|
This DLL must reside somewhere that the debugger has permission to load from, i.e. not in the
|
||||||
values are detected. If anyone understand how to extend this search (or knows how to set the base address to sidestep the scan),
|
WindowsApps directory tree. The <B>exdiConfigData</B> file should be configured for the target
|
||||||
we would really love some guidance.
|
you're using. We heavily recommend using <B>displayCommPackets==yes</B>, as many of the tasks
|
||||||
</P>
|
take considerable time, and this is the only indicator of progress.</P>
|
||||||
|
|
||||||
|
<P>The <B>Kd=Guess</B> parameter causes the underlying engine to scan memory for the kernel's
|
||||||
|
base address, which will probably not be provided by the gdbstub. (<B>Kd=NtBaseAddr</B> 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.</P>
|
||||||
|
|
||||||
<H3><A name="dbgeng_ttd"></A>TTD (Time-Travel Debugging)</H3>
|
<H3><A name="dbgeng_ttd"></A>TTD (Time-Travel Debugging)</H3>
|
||||||
|
|
||||||
|
|
|
@ -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.magenta = rgb(249,53,248)
|
||||||
color.fg.plugin.terminal.bright.cyan = rgb(20,240,240)
|
color.fg.plugin.terminal.bright.cyan = rgb(20,240,240)
|
||||||
color.fg.plugin.terminal.bright.white = rgb(233,235,235)
|
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
|
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.tabs.list = sansserif-bold-9
|
||||||
font.plugin.tips = dialog-plain-12
|
font.plugin.tips = dialog-plain-12
|
||||||
font.plugin.tips.label = font.plugin.tips[bold]
|
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.terminal.completion.list = dialog-plain-12
|
||||||
font.plugin.window.location = font.monospaced[40]
|
font.plugin.window.location = font.monospaced[40]
|
||||||
|
|
||||||
|
|
|
@ -35,8 +35,9 @@ public class TerminalLayout extends SingleRowLayout {
|
||||||
protected final VtLine line;
|
protected final VtLine line;
|
||||||
protected final TerminalTextField field;
|
protected final TerminalTextField field;
|
||||||
|
|
||||||
public TerminalLayout(VtLine line, FontMetrics metrics, AnsiColorResolver colors) {
|
public TerminalLayout(VtLine line, FontMetrics metrics, float fontSizeAdjustment,
|
||||||
super(TerminalTextField.create(line, metrics, colors));
|
AnsiColorResolver colors) {
|
||||||
|
super(TerminalTextField.create(line, metrics, fontSizeAdjustment, colors));
|
||||||
this.line = line;
|
this.line = line;
|
||||||
this.field = (TerminalTextField) getField(0);
|
this.field = (TerminalTextField) getField(0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,7 @@ import docking.widgets.fieldpanel.listener.LayoutModelListener;
|
||||||
import docking.widgets.fieldpanel.support.FieldLocation;
|
import docking.widgets.fieldpanel.support.FieldLocation;
|
||||||
import docking.widgets.fieldpanel.support.FieldRange;
|
import docking.widgets.fieldpanel.support.FieldRange;
|
||||||
import ghidra.app.plugin.core.terminal.vt.*;
|
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.app.plugin.core.terminal.vt.VtCharset.G;
|
||||||
import ghidra.util.*;
|
import ghidra.util.*;
|
||||||
|
|
||||||
|
@ -65,6 +66,7 @@ public class TerminalLayoutModel implements LayoutModel, VtHandler {
|
||||||
|
|
||||||
// Rendering properties
|
// Rendering properties
|
||||||
protected FontMetrics metrics;
|
protected FontMetrics metrics;
|
||||||
|
protected float fontSizeAdjustment;
|
||||||
protected final AnsiColorResolver colors;
|
protected final AnsiColorResolver colors;
|
||||||
|
|
||||||
protected final ArrayList<LayoutModelListener> listeners = new ArrayList<>();
|
protected final ArrayList<LayoutModelListener> 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 panel the panel to receive commands from the model's VT/ANSI parser
|
||||||
* @param charset the charset for decoding bytes to characters
|
* @param charset the charset for decoding bytes to characters
|
||||||
* @param metrics font metrics for the monospaced terminal font
|
* @param metrics font metrics for the monospaced terminal font
|
||||||
|
* @param fontSizeAdjustment the font size adjustment
|
||||||
* @param colors a resolver for ANSI colors
|
* @param colors a resolver for ANSI colors
|
||||||
*/
|
*/
|
||||||
public TerminalLayoutModel(TerminalPanel panel, Charset charset, FontMetrics metrics,
|
public TerminalLayoutModel(TerminalPanel panel, Charset charset, FontMetrics metrics,
|
||||||
|
@ -202,7 +205,7 @@ public class TerminalLayoutModel implements LayoutModel, VtHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected TerminalLayout newLayout(VtLine line) {
|
protected TerminalLayout newLayout(VtLine line) {
|
||||||
return new TerminalLayout(line, metrics, colors);
|
return new TerminalLayout(line, metrics, fontSizeAdjustment, colors);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void buildLayouts() {
|
protected void buildLayouts() {
|
||||||
|
@ -371,7 +374,7 @@ public class TerminalLayoutModel implements LayoutModel, VtHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleReverseVideo(boolean reverse) {
|
public void handleReverseVideo(ReverseVideo reverse) {
|
||||||
buffer.setAttributes(buffer.getAttributes().reverseVideo(reverse));
|
buffer.setAttributes(buffer.getAttributes().reverseVideo(reverse));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -412,7 +415,7 @@ public class TerminalLayoutModel implements LayoutModel, VtHandler {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleAutoWrapMode(boolean en) {
|
public void handleAutoWrapMode(boolean en) {
|
||||||
System.err.println("TODO: handleAutoWrapMode: " + en);
|
Msg.trace(this, "TODO: handleAutoWrapMode: " + en);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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();
|
layouts.clear();
|
||||||
layoutCache.clear();
|
layoutCache.clear();
|
||||||
buildLayouts();
|
buildLayouts();
|
||||||
|
|
|
@ -33,8 +33,7 @@ import docking.widgets.fieldpanel.field.Field;
|
||||||
import docking.widgets.fieldpanel.listener.*;
|
import docking.widgets.fieldpanel.listener.*;
|
||||||
import docking.widgets.fieldpanel.support.*;
|
import docking.widgets.fieldpanel.support.*;
|
||||||
import docking.widgets.indexedscrollpane.IndexedScrollPane;
|
import docking.widgets.indexedscrollpane.IndexedScrollPane;
|
||||||
import generic.theme.GColor;
|
import generic.theme.*;
|
||||||
import generic.theme.Gui;
|
|
||||||
import ghidra.app.plugin.core.terminal.TerminalFinder.RegexTerminalFinder;
|
import ghidra.app.plugin.core.terminal.TerminalFinder.RegexTerminalFinder;
|
||||||
import ghidra.app.plugin.core.terminal.TerminalFinder.TextTerminalFinder;
|
import ghidra.app.plugin.core.terminal.TerminalFinder.TextTerminalFinder;
|
||||||
import ghidra.app.plugin.core.terminal.vt.*;
|
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.
|
* most sense to declare the various {@link GColor}s here.
|
||||||
*/
|
*/
|
||||||
public class TerminalPanel extends JPanel implements FieldLocationListener, FieldSelectionListener,
|
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 int MAX_TITLE_STACK_SIZE = 20;
|
||||||
|
|
||||||
protected static final String DEFAULT_FONT_ID = "font.plugin.terminal";
|
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<String> 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_BACKGROUND = new GColor("color.bg.plugin.terminal");
|
||||||
protected static final GColor COLOR_FOREGROUND = new GColor("color.fg.plugin.terminal");
|
protected static final GColor COLOR_FOREGROUND = new GColor("color.fg.plugin.terminal");
|
||||||
protected static final GColor COLOR_CURSOR_FOCUSED =
|
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");
|
new GColor("color.fg.plugin.terminal.normal.cyan");
|
||||||
protected static final GColor COLOR_7_WHITE =
|
protected static final GColor COLOR_7_WHITE =
|
||||||
new GColor("color.fg.plugin.terminal.normal.white");
|
new GColor("color.fg.plugin.terminal.normal.white");
|
||||||
|
|
||||||
protected static final GColor COLOR_0_BRIGHT_BLACK =
|
protected static final GColor COLOR_0_BRIGHT_BLACK =
|
||||||
new GColor("color.fg.plugin.terminal.bright.black");
|
new GColor("color.fg.plugin.terminal.bright.black");
|
||||||
protected static final GColor COLOR_1_BRIGHT_RED =
|
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 =
|
protected static final GColor COLOR_7_BRIGHT_WHITE =
|
||||||
new GColor("color.fg.plugin.terminal.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 = {
|
protected static final int[] CUBE_STEPS = {
|
||||||
0, 95, 135, 175, 215, 255
|
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 FontMetrics metrics;
|
||||||
protected final TerminalLayoutModel model;
|
protected final TerminalLayoutModel model;
|
||||||
protected final TerminalFieldPanel fieldPanel;
|
protected final TerminalFieldPanel fieldPanel;
|
||||||
|
@ -153,6 +191,7 @@ public class TerminalPanel extends JPanel implements FieldLocationListener, Fiel
|
||||||
this.provider = provider;
|
this.provider = provider;
|
||||||
clipboardProvider = new TerminalClipboardProvider(provider);
|
clipboardProvider = new TerminalClipboardProvider(provider);
|
||||||
Gui.registerFont(this, DEFAULT_FONT_ID);
|
Gui.registerFont(this, DEFAULT_FONT_ID);
|
||||||
|
Gui.addThemeListener(this);
|
||||||
this.metrics = getFontMetrics(getFont());
|
this.metrics = getFontMetrics(getFont());
|
||||||
this.model = new TerminalLayoutModel(this, charset, metrics, this);
|
this.model = new TerminalLayoutModel(this, charset, metrics, this);
|
||||||
this.fieldPanel = new TerminalFieldPanel(model);
|
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
|
@Override
|
||||||
public void setFont(Font font) {
|
public void setFont(Font font) {
|
||||||
super.setFont(font);
|
super.setFont(font);
|
||||||
this.metrics = getFontMetrics(font);
|
updateFontMetrics();
|
||||||
if (model != null) {
|
|
||||||
model.setFontMetrics(this.metrics);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void increaseFontSize() {
|
||||||
|
fontSizeAdjustment++;
|
||||||
|
updateFontMetrics();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void decreaseFontSize() {
|
||||||
|
fontSizeAdjustment--;
|
||||||
|
updateFontMetrics();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void resetFontSize() {
|
||||||
|
fontSizeAdjustment = 0;
|
||||||
|
updateFontMetrics();
|
||||||
}
|
}
|
||||||
|
|
||||||
public TerminalFieldPanel getFieldPanel() {
|
public TerminalFieldPanel getFieldPanel() {
|
||||||
|
@ -424,21 +507,33 @@ public class TerminalPanel extends JPanel implements FieldLocationListener, Fiel
|
||||||
model.processInput(buffer);
|
model.processInput(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Color resolveDefaultColor(WhichGround ground, boolean reverseVideo) {
|
protected Color resolveDefaultColor(WhichGround ground, ReverseVideo reverse,
|
||||||
if (ground == WhichGround.BACKGROUND) {
|
Intensity intensity) {
|
||||||
if (reverseVideo) {
|
Color color = switch (reverse) {
|
||||||
return COLOR_FOREGROUND;
|
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;
|
||||||
}
|
}
|
||||||
return null; // background is already drawn
|
return switch (intensity) {
|
||||||
}
|
case NORMAL -> color;
|
||||||
if (reverseVideo) {
|
case BOLD -> color.brighter();
|
||||||
return COLOR_BACKGROUND;
|
case DIM -> color.darker();
|
||||||
}
|
};
|
||||||
return COLOR_FOREGROUND;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Color resolveStandardColor(AnsiStandardColor standard) {
|
protected Color resolveStandardColor(AnsiStandardColor standard, Intensity intensity) {
|
||||||
return switch (standard) {
|
return switch (intensity) {
|
||||||
|
case BOLD -> resolveIntenseColor(standard.intense);
|
||||||
|
case DIM -> resolveDimColor(standard.dim);
|
||||||
|
case NORMAL -> switch (standard) {
|
||||||
case BLACK -> COLOR_0_BLACK;
|
case BLACK -> COLOR_0_BLACK;
|
||||||
case RED -> COLOR_1_RED;
|
case RED -> COLOR_1_RED;
|
||||||
case GREEN -> COLOR_2_GREEN;
|
case GREEN -> COLOR_2_GREEN;
|
||||||
|
@ -448,6 +543,7 @@ public class TerminalPanel extends JPanel implements FieldLocationListener, Fiel
|
||||||
case CYAN -> COLOR_6_CYAN;
|
case CYAN -> COLOR_6_CYAN;
|
||||||
case WHITE -> COLOR_7_WHITE;
|
case WHITE -> COLOR_7_WHITE;
|
||||||
};
|
};
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Color resolveIntenseColor(AnsiIntenseColor intense) {
|
protected Color resolveIntenseColor(AnsiIntenseColor intense) {
|
||||||
|
@ -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) {
|
protected Color resolve216Color(Ansi216Color cube) {
|
||||||
return ColorUtils.getColor(CUBE_STEPS[cube.r()], CUBE_STEPS[cube.g()],
|
return ColorUtils.getColor(CUBE_STEPS[cube.r()], CUBE_STEPS[cube.g()],
|
||||||
CUBE_STEPS[cube.b()]);
|
CUBE_STEPS[cube.b()]);
|
||||||
|
@ -478,12 +587,12 @@ public class TerminalPanel extends JPanel implements FieldLocationListener, Fiel
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Color resolveColor(AnsiColor color, WhichGround ground, Intensity intensity,
|
public Color resolveColor(AnsiColor color, WhichGround ground, Intensity intensity,
|
||||||
boolean reverseVideo) {
|
ReverseVideo reverse) {
|
||||||
if (color == AnsiDefaultColor.INSTANCE) {
|
if (color == AnsiDefaultColor.INSTANCE) {
|
||||||
return resolveDefaultColor(ground, reverseVideo);
|
return resolveDefaultColor(ground, reverse, intensity);
|
||||||
}
|
}
|
||||||
if (color instanceof AnsiStandardColor standard) {
|
if (color instanceof AnsiStandardColor standard) {
|
||||||
return resolveStandardColor(standard);
|
return resolveStandardColor(standard, intensity);
|
||||||
}
|
}
|
||||||
if (color instanceof AnsiIntenseColor intense) {
|
if (color instanceof AnsiIntenseColor intense) {
|
||||||
return resolveIntenseColor(intense);
|
return resolveIntenseColor(intense);
|
||||||
|
@ -560,6 +669,8 @@ public class TerminalPanel extends JPanel implements FieldLocationListener, Fiel
|
||||||
}
|
}
|
||||||
|
|
||||||
public void dispose() {
|
public void dispose() {
|
||||||
|
Gui.unRegisterFont(this, DEFAULT_FONT_ID);
|
||||||
|
Gui.removeThemeListener(this);
|
||||||
if (this.clipboardService != null) {
|
if (this.clipboardService != null) {
|
||||||
clipboardService.deRegisterClipboardContentProvider(clipboardProvider);
|
clipboardService.deRegisterClipboardContentProvider(clipboardProvider);
|
||||||
}
|
}
|
||||||
|
@ -663,6 +774,10 @@ public class TerminalPanel extends JPanel implements FieldLocationListener, Fiel
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void resizeTerminalToWindow() {
|
protected void resizeTerminalToWindow() {
|
||||||
|
if (scroller == null) {
|
||||||
|
// Some callback during construction
|
||||||
|
return;
|
||||||
|
}
|
||||||
Rectangle bounds = scroller.getViewportBorderBounds();
|
Rectangle bounds = scroller.getViewportBorderBounds();
|
||||||
int cols = bounds.width / metrics.charWidth('M');
|
int cols = bounds.width / metrics.charWidth('M');
|
||||||
int rows = bounds.height / metrics.getHeight();
|
int rows = bounds.height / metrics.getHeight();
|
||||||
|
|
|
@ -167,6 +167,9 @@ public class TerminalProvider extends ComponentProviderAdapter {
|
||||||
protected DockingAction actionFindPrevious;
|
protected DockingAction actionFindPrevious;
|
||||||
protected DockingAction actionSelectAll;
|
protected DockingAction actionSelectAll;
|
||||||
protected DockingAction actionTerminate;
|
protected DockingAction actionTerminate;
|
||||||
|
protected DockingAction actionIncreaseSize;
|
||||||
|
protected DockingAction actionDecreaseSize;
|
||||||
|
protected DockingAction actionResetSize;
|
||||||
|
|
||||||
private boolean terminated = false;
|
private boolean terminated = false;
|
||||||
|
|
||||||
|
@ -262,6 +265,28 @@ public class TerminalProvider extends ComponentProviderAdapter {
|
||||||
.helpLocation(new HelpLocation(helpPlugin.getName(), "select_all"))
|
.helpLocation(new HelpLocation(helpPlugin.getName(), "select_all"))
|
||||||
.onAction(this::activatedSelectAll)
|
.onAction(this::activatedSelectAll)
|
||||||
.buildAndInstallLocal(this);
|
.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) {
|
protected void activatedFind(ActionContext ctx) {
|
||||||
|
@ -329,6 +354,18 @@ public class TerminalProvider extends ComponentProviderAdapter {
|
||||||
panel.getFieldPanel().setSelection(sel, EventTrigger.GUI_ACTION);
|
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.
|
* Check if the given keystroke would activate a local action.
|
||||||
*
|
*
|
||||||
|
|
|
@ -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 line the line from the {@link VtBuffer} that will be rendered in this field
|
||||||
* @param metrics the font metrics
|
* @param metrics the font metrics
|
||||||
|
* @param fontSizeAdjustment the font size adjustment
|
||||||
* @param colors the color resolver
|
* @param colors the color resolver
|
||||||
* @return the field
|
* @return the field
|
||||||
*/
|
*/
|
||||||
public static TerminalTextField create(VtLine line, FontMetrics metrics,
|
public static TerminalTextField create(VtLine line, FontMetrics metrics,
|
||||||
AnsiColorResolver colors) {
|
float fontSizeAdjustment, AnsiColorResolver colors) {
|
||||||
return new TerminalTextField(0, new TerminalTextFieldElement(line, metrics, colors),
|
return new TerminalTextField(0,
|
||||||
metrics);
|
new TerminalTextFieldElement(line, metrics, fontSizeAdjustment, colors), metrics);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected TerminalTextField(int startX, TerminalTextFieldElement element, FontMetrics metrics) {
|
protected TerminalTextField(int startX, TerminalTextFieldElement element, FontMetrics metrics) {
|
||||||
|
|
|
@ -22,8 +22,8 @@ import javax.swing.JComponent;
|
||||||
|
|
||||||
import docking.widgets.fieldpanel.field.FieldElement;
|
import docking.widgets.fieldpanel.field.FieldElement;
|
||||||
import docking.widgets.fieldpanel.support.RowColLocation;
|
import docking.widgets.fieldpanel.support.RowColLocation;
|
||||||
|
import generic.theme.Gui;
|
||||||
import ghidra.app.plugin.core.terminal.vt.*;
|
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
|
* 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 VtLine line;
|
||||||
protected final FontMetrics metrics;
|
protected final FontMetrics metrics;
|
||||||
|
protected final float fontSizeAdjustment;
|
||||||
protected final AnsiColorResolver colors;
|
protected final AnsiColorResolver colors;
|
||||||
|
|
||||||
protected final int em;
|
protected final int em;
|
||||||
|
@ -50,11 +51,14 @@ public class TerminalTextFieldElement implements FieldElement {
|
||||||
*
|
*
|
||||||
* @param line the line of text from the {@link VtBuffer}
|
* @param line the line of text from the {@link VtBuffer}
|
||||||
* @param metrics the font metrics
|
* @param metrics the font metrics
|
||||||
|
* @param fontSizeAdjustment the font size adjustment
|
||||||
* @param colors the color resolver
|
* @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.line = line;
|
||||||
this.metrics = metrics;
|
this.metrics = metrics;
|
||||||
|
this.fontSizeAdjustment = fontSizeAdjustment;
|
||||||
this.colors = colors;
|
this.colors = colors;
|
||||||
|
|
||||||
this.em = metrics.charWidth('M');
|
this.em = metrics.charWidth('M');
|
||||||
|
@ -163,22 +167,34 @@ public class TerminalTextFieldElement implements FieldElement {
|
||||||
int height = metrics.getHeight();
|
int height = metrics.getHeight();
|
||||||
int left = x + start * em;
|
int left = x + start * em;
|
||||||
int width = em * (end - start);
|
int width = em * (end - start);
|
||||||
Font font = metrics.getFont();
|
|
||||||
Color bg = attrs.resolveBackground(colors);
|
Color bg = attrs.resolveBackground(colors);
|
||||||
if (bg != null) {
|
if (bg != null) {
|
||||||
g.setColor(bg);
|
g.setColor(bg);
|
||||||
g.fillRect(left, descent - height, width, height);
|
g.fillRect(left, descent - height, width, height);
|
||||||
}
|
}
|
||||||
g.setColor(attrs.resolveForeground(colors));
|
g.setColor(attrs.resolveForeground(colors));
|
||||||
// NB. I don't really intend to implement blinking.
|
// I don't really intend to implement blinking.
|
||||||
// TODO: AnsiFont mapping?
|
// We still use metrics from DEFAULT_FONT_ID
|
||||||
if (attrs.intensity() == Intensity.DIM) {
|
Font font = Gui.getFont(switch (attrs.intensity()) {
|
||||||
g.setFont(font.deriveFont(Font.PLAIN));
|
case NORMAL -> switch (attrs.font()) {
|
||||||
}
|
case NORMAL -> TerminalPanel.DEFAULT_FONT_ID;
|
||||||
else {
|
case ITALIC -> TerminalPanel.DEFAULT_ITALIC_FONT_ID;
|
||||||
// Normal will use bold font, but standard color
|
case BLACK_LETTER -> TerminalPanel.DEFAULT_FRAKTUR_FONT_ID;
|
||||||
g.setFont(font.deriveFont(Font.BOLD));
|
};
|
||||||
}
|
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()) {
|
if (!attrs.hidden()) {
|
||||||
switch (attrs.underline()) {
|
switch (attrs.underline()) {
|
||||||
case DOUBLE:
|
case DOUBLE:
|
||||||
|
|
|
@ -32,6 +32,35 @@ public interface AnsiColorResolver {
|
||||||
FOREGROUND, BACKGROUND;
|
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
|
* 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 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
|
* @param intensity gives the intensity of the color, really only used when a basic color is
|
||||||
* specified.
|
* specified.
|
||||||
* @param reverseVideo identifies whether the foreground and background colors were swapped,
|
* @param reverse identifies whether the foreground and background colors were swapped, really
|
||||||
* really only used when the default color is specified.
|
* 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
|
* @return the AWT color, or null to not draw (usually in the case of the default background
|
||||||
* color)
|
* color)
|
||||||
*/
|
*/
|
||||||
Color resolveColor(AnsiColor color, WhichGround ground, Intensity intensity,
|
Color resolveColor(AnsiColor color, WhichGround ground, Intensity intensity,
|
||||||
boolean reverseVideo);
|
ReverseVideo reverse);
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ package ghidra.app.plugin.core.terminal.vt;
|
||||||
|
|
||||||
import java.awt.Color;
|
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.AnsiColorResolver.WhichGround;
|
||||||
import ghidra.app.plugin.core.terminal.vt.VtHandler.*;
|
import ghidra.app.plugin.core.terminal.vt.VtHandler.*;
|
||||||
|
|
||||||
|
@ -30,7 +31,7 @@ import ghidra.app.plugin.core.terminal.vt.VtHandler.*;
|
||||||
* in the buffer.
|
* in the buffer.
|
||||||
*/
|
*/
|
||||||
public record VtAttributes(AnsiColor fg, AnsiColor bg, Intensity intensity,
|
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) {
|
boolean strikeThrough, boolean proportionalSpacing) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -38,8 +39,8 @@ public record VtAttributes(AnsiColor fg, AnsiColor bg, Intensity intensity,
|
||||||
*/
|
*/
|
||||||
public static final VtAttributes DEFAULTS =
|
public static final VtAttributes DEFAULTS =
|
||||||
new VtAttributes(AnsiDefaultColor.INSTANCE, AnsiDefaultColor.INSTANCE,
|
new VtAttributes(AnsiDefaultColor.INSTANCE, AnsiDefaultColor.INSTANCE,
|
||||||
Intensity.NORMAL, AnsiFont.NORMAL, Underline.NONE, Blink.NONE, false, false, false,
|
Intensity.NORMAL, AnsiFont.NORMAL, Underline.NONE, Blink.NONE, ReverseVideo.NORMAL,
|
||||||
false);
|
false, false, false);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a copy of this record with the foreground color replaced
|
* 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
|
* @return the new record
|
||||||
*/
|
*/
|
||||||
public VtAttributes fg(AnsiColor fg) {
|
public VtAttributes fg(AnsiColor fg) {
|
||||||
return new VtAttributes(fg, bg, intensity, font, underline, blink, reverseVideo,
|
return new VtAttributes(fg, bg, intensity, font, underline, blink, reverse, hidden,
|
||||||
hidden, strikeThrough, proportionalSpacing);
|
strikeThrough, proportionalSpacing);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -59,8 +60,8 @@ public record VtAttributes(AnsiColor fg, AnsiColor bg, Intensity intensity,
|
||||||
* @return the new record
|
* @return the new record
|
||||||
*/
|
*/
|
||||||
public VtAttributes bg(AnsiColor bg) {
|
public VtAttributes bg(AnsiColor bg) {
|
||||||
return new VtAttributes(fg, bg, intensity, font, underline, blink, reverseVideo,
|
return new VtAttributes(fg, bg, intensity, font, underline, blink, reverse, hidden,
|
||||||
hidden, strikeThrough, proportionalSpacing);
|
strikeThrough, proportionalSpacing);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -70,8 +71,8 @@ public record VtAttributes(AnsiColor fg, AnsiColor bg, Intensity intensity,
|
||||||
* @return the new record
|
* @return the new record
|
||||||
*/
|
*/
|
||||||
public VtAttributes intensity(Intensity intensity) {
|
public VtAttributes intensity(Intensity intensity) {
|
||||||
return new VtAttributes(fg, bg, intensity, font, underline, blink, reverseVideo,
|
return new VtAttributes(fg, bg, intensity, font, underline, blink, reverse, hidden,
|
||||||
hidden, strikeThrough, proportionalSpacing);
|
strikeThrough, proportionalSpacing);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -81,8 +82,8 @@ public record VtAttributes(AnsiColor fg, AnsiColor bg, Intensity intensity,
|
||||||
* @return the new record
|
* @return the new record
|
||||||
*/
|
*/
|
||||||
public VtAttributes font(AnsiFont font) {
|
public VtAttributes font(AnsiFont font) {
|
||||||
return new VtAttributes(fg, bg, intensity, font, underline, blink, reverseVideo,
|
return new VtAttributes(fg, bg, intensity, font, underline, blink, reverse, hidden,
|
||||||
hidden, strikeThrough, proportionalSpacing);
|
strikeThrough, proportionalSpacing);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -92,8 +93,8 @@ public record VtAttributes(AnsiColor fg, AnsiColor bg, Intensity intensity,
|
||||||
* @return the new record
|
* @return the new record
|
||||||
*/
|
*/
|
||||||
public VtAttributes underline(Underline underline) {
|
public VtAttributes underline(Underline underline) {
|
||||||
return new VtAttributes(fg, bg, intensity, font, underline, blink, reverseVideo,
|
return new VtAttributes(fg, bg, intensity, font, underline, blink, reverse, hidden,
|
||||||
hidden, strikeThrough, proportionalSpacing);
|
strikeThrough, proportionalSpacing);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -103,19 +104,19 @@ public record VtAttributes(AnsiColor fg, AnsiColor bg, Intensity intensity,
|
||||||
* @return the new record
|
* @return the new record
|
||||||
*/
|
*/
|
||||||
public VtAttributes blink(Blink blink) {
|
public VtAttributes blink(Blink blink) {
|
||||||
return new VtAttributes(fg, bg, intensity, font, underline, blink, reverseVideo,
|
return new VtAttributes(fg, bg, intensity, font, underline, blink, reverse, hidden,
|
||||||
hidden, strikeThrough, proportionalSpacing);
|
strikeThrough, proportionalSpacing);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a copy of this record with the reverse-video replaced
|
* 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
|
* @return the new record
|
||||||
*/
|
*/
|
||||||
public VtAttributes reverseVideo(boolean reverseVideo) {
|
public VtAttributes reverseVideo(ReverseVideo reverse) {
|
||||||
return new VtAttributes(fg, bg, intensity, font, underline, blink, reverseVideo,
|
return new VtAttributes(fg, bg, intensity, font, underline, blink, reverse, hidden,
|
||||||
hidden, strikeThrough, proportionalSpacing);
|
strikeThrough, proportionalSpacing);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -125,8 +126,8 @@ public record VtAttributes(AnsiColor fg, AnsiColor bg, Intensity intensity,
|
||||||
* @return the new record
|
* @return the new record
|
||||||
*/
|
*/
|
||||||
public VtAttributes hidden(boolean hidden) {
|
public VtAttributes hidden(boolean hidden) {
|
||||||
return new VtAttributes(fg, bg, intensity, font, underline, blink, reverseVideo,
|
return new VtAttributes(fg, bg, intensity, font, underline, blink, reverse, hidden,
|
||||||
hidden, strikeThrough, proportionalSpacing);
|
strikeThrough, proportionalSpacing);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -136,8 +137,8 @@ public record VtAttributes(AnsiColor fg, AnsiColor bg, Intensity intensity,
|
||||||
* @return the new record
|
* @return the new record
|
||||||
*/
|
*/
|
||||||
public VtAttributes strikeThrough(boolean strikeThrough) {
|
public VtAttributes strikeThrough(boolean strikeThrough) {
|
||||||
return new VtAttributes(fg, bg, intensity, font, underline, blink, reverseVideo,
|
return new VtAttributes(fg, bg, intensity, font, underline, blink, reverse, hidden,
|
||||||
hidden, strikeThrough, proportionalSpacing);
|
strikeThrough, proportionalSpacing);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -147,8 +148,8 @@ public record VtAttributes(AnsiColor fg, AnsiColor bg, Intensity intensity,
|
||||||
* @return the new record
|
* @return the new record
|
||||||
*/
|
*/
|
||||||
public VtAttributes proportionalSpacing(boolean proportionalSpacing) {
|
public VtAttributes proportionalSpacing(boolean proportionalSpacing) {
|
||||||
return new VtAttributes(fg, bg, intensity, font, underline, blink, reverseVideo,
|
return new VtAttributes(fg, bg, intensity, font, underline, blink, reverse, hidden,
|
||||||
hidden, strikeThrough, proportionalSpacing);
|
strikeThrough, proportionalSpacing);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -158,8 +159,7 @@ public record VtAttributes(AnsiColor fg, AnsiColor bg, Intensity intensity,
|
||||||
* @return the color
|
* @return the color
|
||||||
*/
|
*/
|
||||||
public Color resolveForeground(AnsiColorResolver colors) {
|
public Color resolveForeground(AnsiColorResolver colors) {
|
||||||
return colors.resolveColor(reverseVideo ? bg : fg, WhichGround.FOREGROUND, intensity,
|
return colors.resolveColor(reverse.fg(fg, bg), WhichGround.FOREGROUND, intensity, reverse);
|
||||||
reverseVideo);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -169,7 +169,7 @@ public record VtAttributes(AnsiColor fg, AnsiColor bg, Intensity intensity,
|
||||||
* @return the color, or null to not paint the background
|
* @return the color, or null to not paint the background
|
||||||
*/
|
*/
|
||||||
public Color resolveBackground(AnsiColorResolver colors) {
|
public Color resolveBackground(AnsiColorResolver colors) {
|
||||||
return colors.resolveColor(reverseVideo ? fg : bg, WhichGround.BACKGROUND, Intensity.NORMAL,
|
return colors.resolveColor(reverse.bg(fg, bg), WhichGround.BACKGROUND, Intensity.NORMAL,
|
||||||
reverseVideo);
|
reverse);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ import java.util.PrimitiveIterator.OfInt;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import ghidra.app.plugin.core.terminal.vt.AnsiColorResolver.ReverseVideo;
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -171,43 +172,51 @@ public interface VtHandler {
|
||||||
* Usually the darkest black available. Implementations may select a color softer on the
|
* 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).
|
* 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.
|
* A color whose hue is clearly red.
|
||||||
*/
|
*/
|
||||||
RED,
|
RED(AnsiIntenseColor.RED, AnsiDimColor.RED),
|
||||||
/**
|
/**
|
||||||
* A color whose hue is clearly green.
|
* A color whose hue is clearly green.
|
||||||
*/
|
*/
|
||||||
GREEN,
|
GREEN(AnsiIntenseColor.GREEN, AnsiDimColor.GREEN),
|
||||||
/**
|
/**
|
||||||
* A color whose hue is clearly yellow.
|
* 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)
|
* 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.
|
* 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
|
* 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.
|
* (but not black) background, a hue tinted toward red is recommended.
|
||||||
*/
|
*/
|
||||||
MAGENTA,
|
MAGENTA(AnsiIntenseColor.MAGENTA, AnsiDimColor.MAGENTA),
|
||||||
/**
|
/**
|
||||||
* A color whose hue is clearly cyan.
|
* A color whose hue is clearly cyan.
|
||||||
*/
|
*/
|
||||||
CYAN,
|
CYAN(AnsiIntenseColor.CYAN, AnsiDimColor.CYAN),
|
||||||
/**
|
/**
|
||||||
* A relatively bright white, sparing the brightest for intense white.
|
* A relatively bright white, sparing the brightest for intense white.
|
||||||
*/
|
*/
|
||||||
WHITE;
|
WHITE(AnsiIntenseColor.WHITE, AnsiDimColor.WHITE);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An unmodifiable list giving all the standard colors
|
* An unmodifiable list giving all the standard colors
|
||||||
*/
|
*/
|
||||||
public static final List<AnsiStandardColor> ALL = List.of(AnsiStandardColor.values());
|
public static final List<AnsiStandardColor> 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
|
* 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<AnsiDimColor> ALL = List.of(AnsiDimColor.values());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the dim color for the given numerical code
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* 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
|
* For 8-bit colors, one of the 216 colors from the RGB cube
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* The r, g, and b fields give the "step" number from 0 to 5, dimmest to brightest.
|
* 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
|
* 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 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.
|
* the brightest, but not true white.
|
||||||
*/
|
*/
|
||||||
public record AnsiGrayscaleColor(int v) implements AnsiColor {
|
public record AnsiGrayscaleColor(int v) implements AnsiColor {}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A 24-bit color
|
* A 24-bit color
|
||||||
|
@ -307,8 +370,7 @@ public interface VtHandler {
|
||||||
* <p>
|
* <p>
|
||||||
* The r, g, and b fields are values from 0 to 255 dimmest to brightest.
|
* 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.
|
* Modifies the intensity of the character either by color or by font weight.
|
||||||
|
@ -1202,7 +1264,7 @@ public interface VtHandler {
|
||||||
handleBlink(Blink.FAST);
|
handleBlink(Blink.FAST);
|
||||||
return;
|
return;
|
||||||
case 7:
|
case 7:
|
||||||
handleReverseVideo(true);
|
handleReverseVideo(ReverseVideo.REVERSED);
|
||||||
return;
|
return;
|
||||||
case 8:
|
case 8:
|
||||||
handleHidden(true);
|
handleHidden(true);
|
||||||
|
@ -1232,7 +1294,7 @@ public interface VtHandler {
|
||||||
handleProportionalSpacing(true);
|
handleProportionalSpacing(true);
|
||||||
return;
|
return;
|
||||||
case 27:
|
case 27:
|
||||||
handleReverseVideo(false);
|
handleReverseVideo(ReverseVideo.NORMAL);
|
||||||
return;
|
return;
|
||||||
case 28:
|
case 28:
|
||||||
handleHidden(false);
|
handleHidden(false);
|
||||||
|
@ -1345,9 +1407,9 @@ public interface VtHandler {
|
||||||
* "default background," care must be taken to ensure the foreground is still painted in
|
* "default background," care must be taken to ensure the foreground is still painted in
|
||||||
* reversed mode.
|
* 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
|
* Handle toggling of the hidden attribute
|
||||||
|
|
|
@ -63,6 +63,8 @@ public class TerminalProviderTest extends AbstractGhidraHeadedDebuggerTest {
|
||||||
terminalService = addPlugin(tool, TerminalPlugin.class);
|
terminalService = addPlugin(tool, TerminalPlugin.class);
|
||||||
clipboardService = addPlugin(tool, ClipboardPlugin.class);
|
clipboardService = addPlugin(tool, ClipboardPlugin.class);
|
||||||
|
|
||||||
|
env.showFrontEndTool();
|
||||||
|
|
||||||
PtyFactory factory = PtyFactory.local();
|
PtyFactory factory = PtyFactory.local();
|
||||||
try (Pty pty = factory.openpty()) {
|
try (Pty pty = factory.openpty()) {
|
||||||
Map<String, String> env = new HashMap<>(System.getenv());
|
Map<String, String> env = new HashMap<>(System.getenv());
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue