| /* |
| * Copyright (c) 2002-2019, the original author or authors. |
| * |
| * This software is distributable under the BSD license. See the terms of the |
| * BSD license in the documentation provided with this software. |
| * |
| * https://opensource.org/licenses/BSD-3-Clause |
| */ |
| 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; |
| } |
| |
| } |