2 * This file was taken from:
3 * Jexer - Java Text User Interface
5 * The MIT License (MIT)
7 * Copyright (C) 2017 Kevin Lamonte
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
16 * The above copyright notice and this permission notice shall be included in
17 * all copies or substantial portions of the Software.
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 * DEALINGS IN THE SOFTWARE.
27 * @author Kevin Lamonte [kevin.lamonte@gmail.com]
30 package be
.nikiroo
.utils
;
32 import java
.util
.LinkedList
;
33 import java
.util
.List
;
36 * StringJustifier contains methods to convert one or more long lines of strings
37 * into justified text paragraphs.
39 class StringJustifier
{
41 * Process the given text into a list of left-justified lines of a given
47 * the maximum width of a line
49 * @return the list of justified lines
51 static List
<String
> left2(final String data
, final int width
) {
52 List
<String
> result
= new LinkedList
<String
>();
58 * Left-justify a string into a list of lines.
63 * the maximum number of characters in a line
64 * @return the list of lines
66 static List
<String
> left(final String str
, final int n
) {
67 List
<String
> result
= new LinkedList
<String
>();
72 * 1. Split on '\n' into paragraphs.
74 * 2. Scan each line, noting the position of the last
75 * beginning-of-a-word.
77 * 3. Chop at the last #2 if the next beginning-of-a-word exceeds n.
79 * 4. Return the lines.
82 String
[] rawLines
= str
.split("\n");
83 for (int i
= 0; i
< rawLines
.length
; i
++) {
84 StringBuilder line
= new StringBuilder();
85 StringBuilder word
= new StringBuilder();
86 boolean inWord
= false;
87 for (int j
= 0; j
< rawLines
[i
].length(); j
++) {
88 char ch
= rawLines
[i
].charAt(j
);
89 if ((ch
== ' ') || (ch
== '\t')) {
91 // We have just transitioned from a word to
92 // whitespace. See if we have enough space to add
93 // the word to the line.
94 if (word
.length() + line
.length() > n
) {
95 // This word will exceed the line length. Wrap
97 result
.add(line
.toString());
98 line
= new StringBuilder();
100 if ((word
.toString().startsWith(" "))
101 && (line
.length() == 0)) {
102 line
.append(word
.substring(1));
106 word
= new StringBuilder();
110 // We are in the whitespace before another word. Do
114 if (inWord
== true) {
115 // We are appending to a word.
118 // We have transitioned from whitespace to a word.
125 if (word
.length() + line
.length() > n
) {
126 // This word will exceed the line length. Wrap at it
128 result
.add(line
.toString());
129 line
= new StringBuilder();
131 if ((word
.toString().startsWith(" ")) && (line
.length() == 0)) {
132 line
.append(word
.substring(1));
136 result
.add(line
.toString());
143 * Right-justify a string into a list of lines.
148 * the maximum number of characters in a line
149 * @return the list of lines
151 static List
<String
> right(final String str
, final int n
) {
152 List
<String
> result
= new LinkedList
<String
>();
155 * Same as left(), but preceed each line with spaces to make it n chars
158 List
<String
> lines
= left(str
, n
);
159 for (String line
: lines
) {
160 StringBuilder sb
= new StringBuilder();
161 for (int i
= 0; i
< n
- line
.length(); i
++) {
165 result
.add(sb
.toString());
172 * Center a string into a list of lines.
177 * the maximum number of characters in a line
178 * @return the list of lines
180 static List
<String
> center(final String str
, final int n
) {
181 List
<String
> result
= new LinkedList
<String
>();
184 * Same as left(), but preceed/succeed each line with spaces to make it
187 List
<String
> lines
= left(str
, n
);
188 for (String line
: lines
) {
189 StringBuilder sb
= new StringBuilder();
190 int l
= (n
- line
.length()) / 2;
191 int r
= n
- line
.length() - l
;
192 for (int i
= 0; i
< l
; i
++) {
196 for (int i
= 0; i
< r
; i
++) {
199 result
.add(sb
.toString());
206 * Fully-justify a string into a list of lines.
211 * the maximum number of characters in a line
212 * @return the list of lines
214 static List
<String
> full(final String str
, final int n
) {
215 List
<String
> result
= new LinkedList
<String
>();
218 * Same as left(), but insert spaces between words to make each line n
219 * chars long. The "algorithm" here is pretty dumb: it performs a split
220 * on space and then re-inserts multiples of n between words.
222 List
<String
> lines
= left(str
, n
);
223 for (int lineI
= 0; lineI
< lines
.size() - 1; lineI
++) {
224 String line
= lines
.get(lineI
);
225 String
[] words
= line
.split(" ");
226 if (words
.length
> 1) {
228 for (int i
= 0; i
< words
.length
; i
++) {
229 charCount
+= words
[i
].length();
231 int spaceCount
= n
- charCount
;
232 int q
= spaceCount
/ (words
.length
- 1);
233 int r
= spaceCount
% (words
.length
- 1);
234 StringBuilder sb
= new StringBuilder();
235 for (int i
= 0; i
< words
.length
- 1; i
++) {
237 for (int j
= 0; j
< q
; j
++) {
245 for (int j
= 0; j
< r
; j
++) {
248 sb
.append(words
[words
.length
- 1]);
249 result
.add(sb
.toString());
254 if (lines
.size() > 0) {
255 result
.add(lines
.get(lines
.size() - 1));