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 * I added some changes to integrate it here.
33 package be
.nikiroo
.utils
;
35 import java
.util
.LinkedList
;
36 import java
.util
.List
;
39 * StringJustifier contains methods to convert one or more long lines of strings
40 * into justified text paragraphs.
42 class StringJustifier
{
44 * Process the given text into a list of left-justified lines of a given
50 * the maximum width of a line
52 * @return the list of justified lines
54 static List
<String
> left(final String data
, final int width
) {
55 return left(data
, width
, false);
59 * Right-justify a string into a list of lines.
64 * the maximum number of characters in a line
65 * @return the list of lines
67 static List
<String
> right(final String str
, final int n
) {
68 List
<String
> result
= new LinkedList
<String
>();
71 * Same as left(), but preceed each line with spaces to make it n chars
74 List
<String
> lines
= left(str
, n
);
75 for (String line
: lines
) {
76 StringBuilder sb
= new StringBuilder();
77 for (int i
= 0; i
< n
- line
.length(); i
++) {
81 result
.add(sb
.toString());
88 * Center a string into a list of lines.
93 * the maximum number of characters in a line
94 * @return the list of lines
96 static List
<String
> center(final String str
, final int n
) {
97 List
<String
> result
= new LinkedList
<String
>();
100 * Same as left(), but preceed/succeed each line with spaces to make it
103 List
<String
> lines
= left(str
, n
);
104 for (String line
: lines
) {
105 StringBuilder sb
= new StringBuilder();
106 int l
= (n
- line
.length()) / 2;
107 int r
= n
- line
.length() - l
;
108 for (int i
= 0; i
< l
; i
++) {
112 for (int i
= 0; i
< r
; i
++) {
115 result
.add(sb
.toString());
122 * Fully-justify a string into a list of lines.
127 * the maximum number of characters in a line
128 * @return the list of lines
130 static List
<String
> full(final String str
, final int n
) {
131 List
<String
> result
= new LinkedList
<String
>();
134 * Same as left(true), but insert spaces between words to make each line
135 * n chars long. The "algorithm" here is pretty dumb: it performs a
136 * split on space and then re-inserts multiples of n between words.
138 List
<String
> lines
= left(str
, n
, true);
139 for (int lineI
= 0; lineI
< lines
.size() - 1; lineI
++) {
140 String line
= lines
.get(lineI
);
141 String
[] words
= line
.split(" ");
142 if (words
.length
> 1) {
144 for (int i
= 0; i
< words
.length
; i
++) {
145 charCount
+= words
[i
].length();
147 int spaceCount
= n
- charCount
;
148 int q
= spaceCount
/ (words
.length
- 1);
149 int r
= spaceCount
% (words
.length
- 1);
150 StringBuilder sb
= new StringBuilder();
151 for (int i
= 0; i
< words
.length
- 1; i
++) {
153 for (int j
= 0; j
< q
; j
++) {
161 for (int j
= 0; j
< r
; j
++) {
164 sb
.append(words
[words
.length
- 1]);
165 result
.add(sb
.toString());
170 if (lines
.size() > 0) {
171 result
.add(lines
.get(lines
.size() - 1));
178 * Process the given text into a list of left-justified lines of a given
182 * the text to justify
184 * the maximum width of a line
186 * use 2 words per line minimum if the text allows it
188 * @return the list of justified lines
190 static private List
<String
> left(final String data
, final int width
,
191 boolean minTwoWords
) {
192 List
<String
> lines
= new LinkedList
<String
>();
194 for (String dataLine
: data
.split("\n")) {
195 String line
= rightTrim(dataLine
.replace("\t", " "));
197 if (width
> 0 && line
.length() > width
) {
198 while (line
.length() > 0) {
199 int i
= Math
.min(line
.length(), width
- 1); // -1 for "-"
201 boolean needDash
= true;
202 // find the best space if any and if needed
204 if (i
< line
.length()) {
206 int space
= line
.indexOf(' ');
209 while (space
> -1 && space
<= i
) {
211 space
= line
.indexOf(' ', space
+ 1);
215 if (prevSpace
> 0 && (!minTwoWords
|| numOfSpaces
>= 2)) {
222 // no dash before space/dash
223 if ((i
+ 1) < line
.length()) {
224 char car
= line
.charAt(i
);
225 char nextCar
= line
.charAt(i
+ 1);
226 if (car
== ' ' || car
== '-' || nextCar
== ' ') {
229 char prevCar
= line
.charAt(i
- 1);
230 if (prevCar
== ' ' || prevCar
== '-') {
237 // if the space freed by the removed dash allows it, or if
238 // it is the last char, add the next char
239 if (!needDash
|| i
>= line
.length() - 1) {
240 int checkI
= Math
.min(i
+ 1, line
.length());
241 if (checkI
== i
|| checkI
<= width
) {
247 // no dash before parenthesis (but cannot add one more
249 if ((i
+ 1) < line
.length()) {
250 char nextCar
= line
.charAt(i
+ 1);
251 if (nextCar
== '(' || nextCar
== ')') {
257 lines
.add(rightTrim(line
.substring(0, i
)) + "-");
259 lines
.add(rightTrim(line
.substring(0, i
)));
262 // full trim (remove spaces when cutting)
263 line
= line
.substring(i
).trim();
274 * Trim the given {@link String} on the right only.
277 * the source {@link String}
278 * @return the right-trimmed String or Empty if it was NULL
280 static private String
rightTrim(String data
) {
284 return ("|" + data
).trim().substring(1);