diff --git a/src/com/fsck/k9/helper/HtmlConverter.java b/src/com/fsck/k9/helper/HtmlConverter.java index 2002f2767..275e50820 100644 --- a/src/com/fsck/k9/helper/HtmlConverter.java +++ b/src/com/fsck/k9/helper/HtmlConverter.java @@ -211,87 +211,54 @@ public class HtmlConverter { } StringReader reader = new StringReader(text); StringBuilder buff = new StringBuilder(text.length() + TEXT_TO_HTML_EXTRA_BUFFER_LENGTH); - boolean isStartOfLine = false; // Are we currently at the start of a line? + boolean isStartOfLine = true; // Are we currently at the start of a line? int spaces = 0; int quoteDepth = 0; // Number of DIVs deep we are. int quotesThisLine = 0; // How deep we should be quoting for this line. try { int c; while ((c = reader.read()) != -1) { - switch (c) { - case '\n': - case '&': - case '<': - case '\r': - if (isStartOfLine) { - while (spaces-- > 0) { - buff.append(' '); - } - } - else { - spaces = 0; - } - break; - } - - switch (c) { - case '\n': - // pine treats
as two newlines, but
as one newline. Use
so our messages aren't - // doublespaced. - buff.append(HTML_NEWLINE); - isStartOfLine = true; - quotesThisLine = 0; - break; - case '&': - buff.append("&"); - break; - case '<': - buff.append("<"); - break; - case '>': - spaces = 0; - if (isStartOfLine) { - quotesThisLine++; - } else { - // We use a token here which can't occur in htmlified text because > is valid - // within links (where > is not), and linkifying links will include it if we - // do it here. We'll make another pass and change this back to > after - // the linkification is done. - buff.append(""); - } - break; - case '\r': - break; - case ' ': - if (isStartOfLine) { + if (isStartOfLine) { + switch (c) { + case ' ': spaces++; - } - else { - buff.append((char)c); - } - break; - default: - if (isStartOfLine) { - // Not a quote character and not a space. Content is starting now. - isStartOfLine = false; - // Add/remove blockquotes by comparing this line's quotes to the previous line's quotes. - if (quotesThisLine > quoteDepth) { - for (int i = quoteDepth; i < quotesThisLine; i++) { - buff.append(HTML_BLOCKQUOTE_START.replace(HTML_BLOCKQUOTE_COLOR_TOKEN, getQuoteColor(i + 1))); - } - } else if (quotesThisLine < quoteDepth) { - for (int i = quoteDepth; i > quotesThisLine; i--) { - buff.append(HTML_BLOCKQUOTE_END); - } - } + break; + case '>': + quotesThisLine++; + spaces = 0; + break; + case '\n': + appendbq(buff, quotesThisLine, quoteDepth); quoteDepth = quotesThisLine; - while (spaces-- > 0) { - buff.append(' '); - } + appendsp(buff, spaces); + spaces = 0; + + appendchar(buff, c); + isStartOfLine = true; + quotesThisLine = 0; + break; + default: + isStartOfLine = false; + + appendbq(buff, quotesThisLine, quoteDepth); + quoteDepth = quotesThisLine; + + appendsp(buff, spaces); + spaces = 0; + + appendchar(buff, c); + isStartOfLine = false; + break; } - buff.append((char)c); - }//switch + } + else { + appendchar(buff, c); + if (c == '\n') { + isStartOfLine = true; + quotesThisLine = 0; + } + } } } catch (IOException e) { //Should never happen @@ -335,6 +302,54 @@ public class HtmlConverter { return text; } + private static void appendchar(StringBuilder buff, int c) { + switch (c) { + case '&': + buff.append("&"); + break; + case '<': + buff.append("<"); + break; + case '>': + // We use a token here which can't occur in htmlified text because > is valid + // within links (where > is not), and linkifying links will include it if we + // do it here. We'll make another pass and change this back to > after + // the linkification is done. + buff.append(""); + break; + case '\r': + break; + case '\n': + // pine treats
as two newlines, but
as one newline. Use
so our messages aren't + // doublespaced. + buff.append(HTML_NEWLINE); + break; + default: + buff.append((char)c); + break; + } + } + + private static void appendsp(StringBuilder buff, int spaces) { + while (spaces > 0) { + buff.append(' '); + spaces--; + } + } + + private static void appendbq(StringBuilder buff, int quotesThisLine, int quoteDepth) { + // Add/remove blockquotes by comparing this line's quotes to the previous line's quotes. + if (quotesThisLine > quoteDepth) { + for (int i = quoteDepth; i < quotesThisLine; i++) { + buff.append(HTML_BLOCKQUOTE_START.replace(HTML_BLOCKQUOTE_COLOR_TOKEN, getQuoteColor(i + 1))); + } + } else if (quotesThisLine < quoteDepth) { + for (int i = quoteDepth; i > quotesThisLine; i--) { + buff.append(HTML_BLOCKQUOTE_END); + } + } + } + protected static final String QUOTE_COLOR_DEFAULT = "#ccc"; protected static final String QUOTE_COLOR_LEVEL_1 = "#729fcf"; protected static final String QUOTE_COLOR_LEVEL_2 = "#ad7fa8"; diff --git a/tests/src/com/fsck/k9/helper/HtmlConverterTest.java b/tests/src/com/fsck/k9/helper/HtmlConverterTest.java index a58e25050..e5477be78 100644 --- a/tests/src/com/fsck/k9/helper/HtmlConverterTest.java +++ b/tests/src/com/fsck/k9/helper/HtmlConverterTest.java @@ -36,7 +36,8 @@ public class HtmlConverterTest extends TestCase { + "
" + "A man, a plan...
" + "
" - + " Too easy!" + + " Too easy!
" + + "" + "
" + "Nice job :)
" + "
" @@ -137,23 +138,33 @@ public class HtmlConverterTest extends TestCase { public void testPreserveSpacesAtFirst() { String message = "foo\n" + " bar\n" - + " baz\n" - + " \n" - + " &\n" - + " \r\n" - + " <\n" - + " >\n"; + + " baz\n"; String result = HtmlConverter.textToHtml(message); writeToFile(result); assertEquals("
"
                 + "foo
" + " bar
" + " baz
" + + "
", result); + } + + public void testPreserveSpacesAtFirstForSpecialCharacters() { + String message = + " \n" + + " &\n" + + " \r\n" + + " <\n" + + " > \n"; + String result = HtmlConverter.textToHtml(message); + writeToFile(result); + assertEquals("
"
                 + " 
" + " &
" + "
" + " <
" - + " >
" + + "
" + + "
" + + "
" + "
", result); } }