in mailet/base/src/main/java/org/apache/mailet/base/FlowedMessageUtils.java [207:341]
public static String flow(String text, boolean delSp, int width) {
int lastIndex = text.length() - 1;
StringBuilder result = new StringBuilder();
int lineStartIndex = 0;
while (lineStartIndex <= lastIndex) {
int quoteDepth = 0;
while (lineStartIndex <= lastIndex && text.charAt(lineStartIndex) == RFC2646_QUOTE) {
quoteDepth++;
lineStartIndex++;
}
if (quoteDepth > 0 && lineStartIndex + 1 <= lastIndex && text.charAt(lineStartIndex) == RFC2646_SPACE) {
lineStartIndex++;
}
// We support both LF and CRLF line endings. To cover both cases we search for LF.
int lineFeedIndex = text.indexOf(LF, lineStartIndex);
boolean lineBreakFound = lineFeedIndex != -1;
int lineEndIndex = lineBreakFound ? lineFeedIndex : text.length();
int nextLineStartIndex = lineBreakFound ? lineFeedIndex + 1 : text.length();
if (lineBreakFound && lineEndIndex > 0 && text.charAt(lineEndIndex - 1) == CR) {
lineEndIndex--;
}
// Special case: signature separator
if (lineEndIndex - lineStartIndex == RFC2646_SIGNATURE.length() &&
text.regionMatches(lineStartIndex, RFC2646_SIGNATURE, 0, RFC2646_SIGNATURE.length())
) {
if (quoteDepth > 0) {
for (int i = 0; i < quoteDepth; i++) {
result.append(RFC2646_QUOTE);
}
result.append(RFC2646_SPACE);
}
result.append(RFC2646_SIGNATURE);
result.append(RFC2646_CRLF);
lineStartIndex = nextLineStartIndex;
continue;
}
// Remove trailing spaces
while (lineEndIndex > lineStartIndex && text.charAt(lineEndIndex - 1) == RFC2646_SPACE) {
lineEndIndex--;
}
// Special case: a quoted line without any content
if (lineStartIndex == lineEndIndex && quoteDepth > 0) {
for (int i = 0; i < quoteDepth; i++) {
result.append(RFC2646_QUOTE);
}
}
while (lineStartIndex < lineEndIndex) {
int prefixLength = 0;
if (quoteDepth == 0) {
if (text.charAt(lineStartIndex) == RFC2646_SPACE || text.charAt(lineStartIndex) == RFC2646_QUOTE ||
lineEndIndex - lineStartIndex >= RFC2646_FROM.length() &&
text.regionMatches(lineStartIndex, RFC2646_FROM, 0, RFC2646_FROM.length())
) {
// This line needs space stuffing
result.append(RFC2646_SPACE);
prefixLength = 1;
}
} else {
for (int i = 0; i < quoteDepth; i++) {
result.append(RFC2646_QUOTE);
}
result.append(RFC2646_SPACE);
prefixLength = quoteDepth + 1;
}
int remainingWidth = width - prefixLength - 1;
if (delSp) {
remainingWidth--;
}
if (remainingWidth < 0) {
remainingWidth = 0;
}
int breakIndex = lineStartIndex + remainingWidth;
if (breakIndex >= lineEndIndex) {
breakIndex = lineEndIndex;
} else {
while (breakIndex >= lineStartIndex &&
(delSp && isAlphaChar(text, breakIndex) || !delSp && text.charAt(breakIndex) != RFC2646_SPACE)
) {
breakIndex--;
}
if (breakIndex < lineStartIndex) {
// Not able to cut a word: skip to word end even if greater than the max width
breakIndex = lineStartIndex + remainingWidth;
while (breakIndex < lineEndIndex &&
((delSp && isAlphaChar(text, breakIndex)) ||
(!delSp && text.charAt(breakIndex) != RFC2646_SPACE))
) {
breakIndex++;
}
}
breakIndex++;
if (breakIndex >= lineEndIndex) {
breakIndex = lineEndIndex;
} else if (Character.isHighSurrogate(text.charAt(breakIndex - 1))) {
// Don't break surrogate pairs apart
breakIndex++;
}
}
result.append(text, lineStartIndex, breakIndex);
if (breakIndex < lineEndIndex) {
if (delSp) {
result.append(RFC2646_SPACE);
}
result.append(RFC2646_CRLF);
}
lineStartIndex = breakIndex;
}
if (lineBreakFound) {
result.append(RFC2646_CRLF);
}
lineStartIndex = nextLineStartIndex;
}
return result.toString();
}