/** * Call this method to make changes done through {@code putCharacter(...)}, {@code putString(...)} * visible on the terminal. The screen will calculate the changes that are required and send the * necessary characters and control sequences to make it so. */ public void refresh() { if (!hasBeenActivated) return; synchronized (mutex) { // If any resize operations are in the queue, execute them resizeScreenIfNeeded(); Map<TerminalPosition, ScreenCharacter> updateMap = new TreeMap<TerminalPosition, ScreenCharacter>(new ScreenPointComparator()); for (int y = 0; y < terminalSize.getRows(); y++) { for (int x = 0; x < terminalSize.getColumns(); x++) { ScreenCharacter c = backbuffer[y][x]; if (!c.equals(visibleScreen[y][x]) || wholeScreenInvalid) { visibleScreen[y][x] = c; // Remember, ScreenCharacter is immutable, we don't need to worry about it being // modified updateMap.put(new TerminalPosition(x, y), c); } } } Writer terminalWriter = new Writer(); terminalWriter.reset(); TerminalPosition previousPoint = null; for (TerminalPosition nextUpdate : updateMap.keySet()) { if (previousPoint == null || previousPoint.getRow() != nextUpdate.getRow() || previousPoint.getColumn() + 1 != nextUpdate.getColumn()) { terminalWriter.setCursorPosition(nextUpdate.getColumn(), nextUpdate.getRow()); } terminalWriter.writeCharacter(updateMap.get(nextUpdate)); previousPoint = nextUpdate; } terminalWriter.setCursorPosition( getCursorPosition().getColumn(), getCursorPosition().getRow()); wholeScreenInvalid = false; } terminal.flush(); }