package jdk.internal.org.jline.utils;
import java.util.Objects;
import java.util.Collections;
import java.util.ArrayList;
import java.util.List;
import jdk.internal.org.jline.terminal.Terminal;
import jdk.internal.org.jline.terminal.impl.AbstractTerminal;
import jdk.internal.org.jline.utils.InfoCmp.Capability;
import jdk.internal.org.jline.terminal.Size;
public class Status {
protected final AbstractTerminal terminal;
protected final boolean supported;
protected List<AttributedString> oldLines = Collections.emptyList();
protected List<AttributedString> linesToRestore = Collections.emptyList();
protected int rows;
protected int columns;
protected boolean force;
protected boolean suspended = false;
protected AttributedString borderString;
protected int border = 0;
public static Status getStatus(Terminal terminal) {
return getStatus(terminal, true);
}
public static Status getStatus(Terminal terminal, boolean create) {
return terminal instanceof AbstractTerminal
? ((AbstractTerminal) terminal).getStatus(create)
: null;
}
public Status(AbstractTerminal terminal) {
this.terminal = Objects.requireNonNull(terminal, "terminal can not be null");
this.supported = terminal.getStringCapability(Capability.change_scroll_region) != null
&& terminal.getStringCapability(Capability.save_cursor) != null
&& terminal.getStringCapability(Capability.restore_cursor) != null
&& terminal.getStringCapability(Capability.cursor_address) != null;
if (supported) {
char borderChar = '\u2700';
AttributedStringBuilder bb = new AttributedStringBuilder();
for (int i = 0; i < 200; i++) {
bb.append(borderChar);
}
borderString = bb.toAttributedString();
resize();
}
}
public void setBorder(boolean border) {
this.border = border ? 1 : 0;
}
public void resize() {
Size size = terminal.getSize();
this.rows = size.getRows();
this.columns = size.getColumns();
this.force = true;
}
public void reset() {
this.force = true;
}
public void hardReset() {
if (suspended) {
return;
}
List<AttributedString> lines = new ArrayList<>(oldLines);
int b = border;
update(null);
border = b;
update(lines);
}
public void redraw() {
if (suspended) {
return;
}
update(oldLines);
}
public void clear() {
privateClear(oldLines.size());
}
private void clearAll() {
int b = border;
border = 0;
privateClear(oldLines.size() + b);
}
private void privateClear(int statusSize) {
List<AttributedString> as = new ArrayList<>();
for (int i = 0; i < statusSize; i++) {
as.add(new AttributedString(""));
}
if (!as.isEmpty()) {
update(as);
}
}
public void update(List<AttributedString> lines) {
if (!supported) {
return;
}
if (lines == null) {
lines = Collections.emptyList();
}
if (suspended) {
linesToRestore = new ArrayList<>(lines);
return;
}
if (lines.isEmpty()) {
clearAll();
}
if (oldLines.equals(lines) && !force) {
return;
}
int statusSize = lines.size() + (lines.size() == 0 ? 0 : border);
int nb = statusSize - oldLines.size() - (oldLines.size() == 0 ? 0 : border);
if (nb > 0) {
for (int i = 0; i < nb; i++) {
terminal.puts(Capability.cursor_down);
}
for (int i = 0; i < nb; i++) {
terminal.puts(Capability.cursor_up);
}
}
terminal.puts(Capability.save_cursor);
terminal.puts(Capability.cursor_address, rows - statusSize, 0);
if (!terminal.puts(Capability.clr_eos)) {
for (int i = rows - statusSize; i < rows; i++) {
terminal.puts(Capability.cursor_address, i, 0);
terminal.puts(Capability.clr_eol);
}
}
if (border == 1 && lines.size() > 0) {
terminal.puts(Capability.cursor_address, rows - statusSize, 0);
borderString.columnSubSequence(0, columns).print(terminal);
}
for (int i = 0; i < lines.size(); i++) {
terminal.puts(Capability.cursor_address, rows - lines.size() + i, 0);
if (lines.get(i).length() > columns) {
AttributedStringBuilder asb = new AttributedStringBuilder();
asb.append(lines.get(i).substring(0, columns - 3)).append("...", new AttributedStyle(AttributedStyle.INVERSE));
asb.toAttributedString().columnSubSequence(0, columns).print(terminal);
} else {
lines.get(i).columnSubSequence(0, columns).print(terminal);
}
}
terminal.puts(Capability.change_scroll_region, 0, rows - 1 - statusSize);
terminal.puts(Capability.restore_cursor);
terminal.flush();
oldLines = new ArrayList<>(lines);
force = false;
}
public void suspend() {
if (suspended) {
return;
}
linesToRestore = new ArrayList<>(oldLines);
int b = border;
update(null);
border = b;
suspended = true;
}
public void restore() {
if (!suspended) {
return;
}
suspended = false;
update(linesToRestore);
linesToRestore = Collections.emptyList();
}
public int size() {
return oldLines.size() + border;
}
}