Change build scripts
[jvcard.git] / src / com / googlecode / lanterna / terminal / swing / TextBuffer.java
1 /*
2 * This file is part of lanterna (http://code.google.com/p/lanterna/).
3 *
4 * lanterna is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 *
17 * Copyright (C) 2010-2015 Martin
18 */
19 package com.googlecode.lanterna.terminal.swing;
20
21 import com.googlecode.lanterna.TerminalTextUtils;
22 import com.googlecode.lanterna.TextCharacter;
23 import com.googlecode.lanterna.TerminalPosition;
24 import com.googlecode.lanterna.TerminalSize;
25 import java.util.ArrayList;
26 import java.util.Iterator;
27 import java.util.LinkedList;
28 import java.util.List;
29 import java.util.ListIterator;
30
31 /**
32 * Contains an entire text buffer used by Swing terminal
33 * @author martin
34 */
35 class TextBuffer {
36 private final int backlog;
37 private final LinkedList<List<TextCharacter>> lineBuffer;
38 private final TextCharacter fillCharacter;
39
40 TextBuffer(int backlog) {
41 this.backlog = backlog;
42 this.lineBuffer = new LinkedList<List<TextCharacter>>();
43 this.fillCharacter = TextCharacter.DEFAULT_CHARACTER;
44
45 //Initialize the content to one line
46 newLine();
47 }
48
49 void clear() {
50 lineBuffer.clear();
51 newLine();
52 }
53
54 void newLine() {
55 ArrayList<TextCharacter> line = new ArrayList<TextCharacter>(200);
56 line.add(fillCharacter);
57 lineBuffer.addFirst(line);
58 }
59
60
61 Iterable<List<TextCharacter>> getVisibleLines(final int visibleRows, final int scrollOffset) {
62 final int length = Math.min(visibleRows, lineBuffer.size());
63 return new Iterable<List<TextCharacter>>() {
64 @Override
65 public Iterator<List<TextCharacter>> iterator() {
66 return new Iterator<List<TextCharacter>>() {
67 private final ListIterator<List<TextCharacter>> listIterator = lineBuffer.subList(scrollOffset, scrollOffset + length).listIterator(length);
68 @Override
69 public boolean hasNext() { return listIterator.hasPrevious(); }
70 @Override
71 public List<TextCharacter> next() { return listIterator.previous(); }
72 @Override
73 public void remove() { listIterator.remove(); }
74 };
75 }
76 };
77 }
78
79 int getNumberOfLines() {
80 return lineBuffer.size();
81 }
82
83 void trimBacklog(int terminalHeight) {
84 while(lineBuffer.size() - terminalHeight > backlog) {
85 lineBuffer.removeLast();
86 }
87 }
88
89 void ensurePosition(TerminalSize terminalSize, TerminalPosition position) {
90 getLine(terminalSize, position);
91 }
92
93 public TextCharacter getCharacter(TerminalSize terminalSize, TerminalPosition position) {
94 return getLine(terminalSize, position).get(position.getColumn());
95 }
96
97 void setCharacter(TerminalSize terminalSize, TerminalPosition currentPosition, TextCharacter terminalCharacter) {
98 List<TextCharacter> line = getLine(terminalSize, currentPosition);
99
100 //If we are replacing a CJK character with a non-CJK character, make the following character empty
101 if(TerminalTextUtils.isCharCJK(line.get(currentPosition.getColumn()).getCharacter()) &&
102 !TerminalTextUtils.isCharCJK(terminalCharacter.getCharacter())) {
103 line.set(currentPosition.getColumn() + 1, terminalCharacter.withCharacter(' '));
104 }
105
106 //Set the character in the buffer
107 line.set(currentPosition.getColumn(), terminalCharacter);
108
109 //Pad CJK character with a trailing space
110 if(TerminalTextUtils.isCharCJK(terminalCharacter.getCharacter()) && currentPosition.getColumn() + 1 < line.size()) {
111 ensurePosition(terminalSize, currentPosition.withRelativeColumn(1));
112 line.set(currentPosition.getColumn() + 1, terminalCharacter.withCharacter(' '));
113 }
114 //If there's a CJK character immediately to our left, reset it
115 if(currentPosition.getColumn() > 0 && TerminalTextUtils.isCharCJK(line.get(currentPosition.getColumn() - 1).getCharacter())) {
116 line.set(currentPosition.getColumn() - 1, line.get(currentPosition.getColumn() - 1).withCharacter(' '));
117 }
118 }
119
120 private List<TextCharacter> getLine(TerminalSize terminalSize, TerminalPosition position) {
121 while(position.getRow() >= lineBuffer.size()) {
122 newLine();
123 }
124 int lineIndex = Math.min(terminalSize.getRows(), lineBuffer.size()) - 1 - position.getRow();
125 List<TextCharacter> line = lineBuffer.get(lineIndex);
126 while(line.size() <= position.getColumn()) {
127 line.add(fillCharacter);
128 }
129 return line;
130 }
131 }