Loading src/com/fsck/k9/helper/HtmlConverter.java +84 −69 Original line number Diff line number Diff line Loading @@ -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 <br> as two newlines, but <br/> as one newline. Use <br/> so our messages aren't // doublespaced. buff.append(HTML_NEWLINE); isStartOfLine = true; quotesThisLine = 0; break; case '&': buff.append("&"); break; case '<': buff.append("<"); case ' ': spaces++; 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("<gt>"); } break; case '\r': spaces = 0; break; case ' ': if (isStartOfLine) { spaces++; } else { buff.append((char)c); } case '\n': appendbq(buff, quotesThisLine, quoteDepth); quoteDepth = quotesThisLine; appendsp(buff, spaces); spaces = 0; appendchar(buff, c); isStartOfLine = true; quotesThisLine = 0; 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); } } appendbq(buff, quotesThisLine, quoteDepth); quoteDepth = quotesThisLine; while (spaces-- > 0) { buff.append(' '); appendsp(buff, spaces); spaces = 0; appendchar(buff, c); isStartOfLine = false; break; } } else { appendchar(buff, c); if (c == '\n') { isStartOfLine = true; quotesThisLine = 0; } } buff.append((char)c); }//switch } } catch (IOException e) { //Should never happen Loading Loading @@ -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("<gt>"); break; case '\r': break; case '\n': // pine treats <br> as two newlines, but <br/> as one newline. Use <br/> 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"; Loading tests/src/com/fsck/k9/helper/HtmlConverterTest.java +19 −8 Original line number Diff line number Diff line Loading @@ -36,7 +36,8 @@ public class HtmlConverterTest extends TestCase { + "<blockquote class=\"gmail_quote\" style=\"margin: 0pt 0pt 1ex 0.8ex; border-left: 1px solid #ad7fa8; padding-left: 1ex;\">" + "A man, a plan...<br />" + "</blockquote>" + " Too easy!</blockquote>" + " Too easy!<br />" + "</blockquote>" + "<br />" + "Nice job :)<br />" + "<blockquote class=\"gmail_quote\" style=\"margin: 0pt 0pt 1ex 0.8ex; border-left: 1px solid #729fcf; padding-left: 1ex;\">" Loading Loading @@ -137,8 +138,19 @@ public class HtmlConverterTest extends TestCase { public void testPreserveSpacesAtFirst() { String message = "foo\n" + " bar\n" + " baz\n" + " \n" + " baz\n"; String result = HtmlConverter.textToHtml(message); writeToFile(result); assertEquals("<pre class=\"k9mail\">" + "foo<br />" + " bar<br />" + " baz<br />" + "</pre>", result); } public void testPreserveSpacesAtFirstForSpecialCharacters() { String message = " \n" + " &\n" + " \r\n" + " <\n" Loading @@ -146,14 +158,13 @@ public class HtmlConverterTest extends TestCase { String result = HtmlConverter.textToHtml(message); writeToFile(result); assertEquals("<pre class=\"k9mail\">" + "foo<br />" + " bar<br />" + " baz<br />" + " <br />" + " &<br />" + " <br />" + " <<br />" + " ><br />" + "<blockquote class=\"gmail_quote\" style=\"margin: 0pt 0pt 1ex 0.8ex; border-left: 1px solid #729fcf; padding-left: 1ex;\">" + " <br />" + "</blockquote>" + "</pre>", result); } } Loading
src/com/fsck/k9/helper/HtmlConverter.java +84 −69 Original line number Diff line number Diff line Loading @@ -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 <br> as two newlines, but <br/> as one newline. Use <br/> so our messages aren't // doublespaced. buff.append(HTML_NEWLINE); isStartOfLine = true; quotesThisLine = 0; break; case '&': buff.append("&"); break; case '<': buff.append("<"); case ' ': spaces++; 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("<gt>"); } break; case '\r': spaces = 0; break; case ' ': if (isStartOfLine) { spaces++; } else { buff.append((char)c); } case '\n': appendbq(buff, quotesThisLine, quoteDepth); quoteDepth = quotesThisLine; appendsp(buff, spaces); spaces = 0; appendchar(buff, c); isStartOfLine = true; quotesThisLine = 0; 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); } } appendbq(buff, quotesThisLine, quoteDepth); quoteDepth = quotesThisLine; while (spaces-- > 0) { buff.append(' '); appendsp(buff, spaces); spaces = 0; appendchar(buff, c); isStartOfLine = false; break; } } else { appendchar(buff, c); if (c == '\n') { isStartOfLine = true; quotesThisLine = 0; } } buff.append((char)c); }//switch } } catch (IOException e) { //Should never happen Loading Loading @@ -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("<gt>"); break; case '\r': break; case '\n': // pine treats <br> as two newlines, but <br/> as one newline. Use <br/> 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"; Loading
tests/src/com/fsck/k9/helper/HtmlConverterTest.java +19 −8 Original line number Diff line number Diff line Loading @@ -36,7 +36,8 @@ public class HtmlConverterTest extends TestCase { + "<blockquote class=\"gmail_quote\" style=\"margin: 0pt 0pt 1ex 0.8ex; border-left: 1px solid #ad7fa8; padding-left: 1ex;\">" + "A man, a plan...<br />" + "</blockquote>" + " Too easy!</blockquote>" + " Too easy!<br />" + "</blockquote>" + "<br />" + "Nice job :)<br />" + "<blockquote class=\"gmail_quote\" style=\"margin: 0pt 0pt 1ex 0.8ex; border-left: 1px solid #729fcf; padding-left: 1ex;\">" Loading Loading @@ -137,8 +138,19 @@ public class HtmlConverterTest extends TestCase { public void testPreserveSpacesAtFirst() { String message = "foo\n" + " bar\n" + " baz\n" + " \n" + " baz\n"; String result = HtmlConverter.textToHtml(message); writeToFile(result); assertEquals("<pre class=\"k9mail\">" + "foo<br />" + " bar<br />" + " baz<br />" + "</pre>", result); } public void testPreserveSpacesAtFirstForSpecialCharacters() { String message = " \n" + " &\n" + " \r\n" + " <\n" Loading @@ -146,14 +158,13 @@ public class HtmlConverterTest extends TestCase { String result = HtmlConverter.textToHtml(message); writeToFile(result); assertEquals("<pre class=\"k9mail\">" + "foo<br />" + " bar<br />" + " baz<br />" + " <br />" + " &<br />" + " <br />" + " <<br />" + " ><br />" + "<blockquote class=\"gmail_quote\" style=\"margin: 0pt 0pt 1ex 0.8ex; border-left: 1px solid #729fcf; padding-left: 1ex;\">" + " <br />" + "</blockquote>" + "</pre>", result); } }