Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f87ff205 authored by Koji Arai's avatar Koji Arai
Browse files

Merge pull request #309 from jca02266/preserve-spaces

Fixed issue 5630: Quotes are missing a space between > and the quoted text
parents 174d172e 4dcf50d1
Loading
Loading
Loading
Loading
+86 −47
Original line number Diff line number Diff line
@@ -211,63 +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) {
                if (isStartOfLine) {
                    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("&amp;");
                    break;
                case '<':
                    buff.append("&lt;");
                    case ' ':
                        spaces++;
                        break;
                    case '>':
                    if (isStartOfLine) {
                        quotesThisLine++;
                    } else {
                        // We use a token here which can't occur in htmlified text because &gt; 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 &gt; after
                        // the linkification is done.
                        buff.append("<gt>");
                    }
                    break;
                case '\r':
                        spaces = 0;
                        break;
                case ' ':
                    if (isStartOfLine) {
                        // If we're still in the start of the line and we have spaces, don't output them, since they
                        // may be collapsed by our div-converting magic.
                    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)));

                        appendbq(buff, quotesThisLine, quoteDepth);
                        quoteDepth = quotesThisLine;

                        appendsp(buff, spaces);
                        spaces = 0;

                        appendchar(buff, c);
                        isStartOfLine = false;
                        break;
                    }
                        } else if (quotesThisLine < quoteDepth) {
                            for (int i = quoteDepth; i > quotesThisLine; i--) {
                                buff.append(HTML_BLOCKQUOTE_END);
                }
                else {
                    appendchar(buff, c);
                    if (c == '\n') {
                        isStartOfLine = true;
                        quotesThisLine = 0;
                    }
                        quoteDepth = quotesThisLine;
                }
                    buff.append((char)c);
                }//switch
            }
        } catch (IOException e) {
            //Should never happen
@@ -311,6 +302,54 @@ public class HtmlConverter {
        return text;
    }

    private static void appendchar(StringBuilder buff, int c) {
        switch (c) {
        case '&':
            buff.append("&amp;");
            break;
        case '<':
            buff.append("&lt;");
            break;
        case '>':
            // We use a token here which can't occur in htmlified text because &gt; 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 &gt; 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";
+87 −3
Original line number Diff line number Diff line
@@ -25,7 +25,27 @@ public class HtmlConverterTest extends TestCase {
            ">> Guess!";
        String result = HtmlConverter.textToHtml(message);
        writeToFile(result);
        assertEquals("<pre class=\"k9mail\">Panama!<br /><br />Bob Barker &lt;bob@aol.com&gt; wrote:<br /><blockquote class=\"gmail_quote\" style=\"margin: 0pt 0pt 1ex 0.8ex; border-left: 1px solid #729fcf; padding-left: 1ex;\">a canal<br /><br />Dorothy Jo Gideon &lt;dorothy@aol.com&gt; espoused:<br /><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><br />Nice job :)<br /><blockquote class=\"gmail_quote\" style=\"margin: 0pt 0pt 1ex 0.8ex; border-left: 1px solid #729fcf; padding-left: 1ex;\"><blockquote class=\"gmail_quote\" style=\"margin: 0pt 0pt 1ex 0.8ex; border-left: 1px solid #ad7fa8; padding-left: 1ex;\">Guess!</blockquote></blockquote></pre>", result);
        assertEquals("<pre class=\"k9mail\">"
            + "Panama!<br />"
            + "<br />"
            + "Bob Barker &lt;bob@aol.com&gt; wrote:<br />"
            + "<blockquote class=\"gmail_quote\" style=\"margin: 0pt 0pt 1ex 0.8ex; border-left: 1px solid #729fcf; padding-left: 1ex;\">"
            +   " a canal<br />"
            +   "<br />"
            +   " Dorothy Jo Gideon &lt;dorothy@aol.com&gt; espoused:<br />"
            +   "<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!<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;\">"
            +     "<blockquote class=\"gmail_quote\" style=\"margin: 0pt 0pt 1ex 0.8ex; border-left: 1px solid #ad7fa8; padding-left: 1ex;\">"
            +     " Guess!"
            +   "</blockquote>"
            + "</blockquote>"
            + "</pre>", result);
    }

    public void testTextQuoteToHtmlBlockquoteIndented() {
@@ -39,7 +59,18 @@ public class HtmlConverterTest extends TestCase {
            "> :)";
        String result = HtmlConverter.textToHtml(message);
        writeToFile(result);
        assertEquals("<pre class=\"k9mail\">*facepalm*<br /><br />Bob Barker &lt;bob@aol.com&gt; wrote:<br /><blockquote class=\"gmail_quote\" style=\"margin: 0pt 0pt 1ex 0.8ex; border-left: 1px solid #729fcf; padding-left: 1ex;\">A wise man once said...<br /><br />LOL F1RST!!!!!<br /><br />:)</blockquote></pre>", result);
        assertEquals("<pre class=\"k9mail\">"
                + "*facepalm*<br />"
                + "<br />"
                + "Bob Barker &lt;bob@aol.com&gt; wrote:<br />"
                + "<blockquote class=\"gmail_quote\" style=\"margin: 0pt 0pt 1ex 0.8ex; border-left: 1px solid #729fcf; padding-left: 1ex;\">"
                +   " A wise man once said...<br />"
                +   "<br />"
                +   "     LOL F1RST!!!!!<br />"
                +   "<br />"
                +   " :)"
                + "</blockquote></pre>", result);

    }

    public void testQuoteDepthColor() {
@@ -62,7 +93,27 @@ public class HtmlConverterTest extends TestCase {
            ">>>>>> six";
        String result = HtmlConverter.textToHtml(message);
        writeToFile(result);
        assertEquals("<pre class=\"k9mail\">zero<br /><blockquote class=\"gmail_quote\" style=\"margin: 0pt 0pt 1ex 0.8ex; border-left: 1px solid #729fcf; padding-left: 1ex;\">one<br /><blockquote class=\"gmail_quote\" style=\"margin: 0pt 0pt 1ex 0.8ex; border-left: 1px solid #ad7fa8; padding-left: 1ex;\">two<br /><blockquote class=\"gmail_quote\" style=\"margin: 0pt 0pt 1ex 0.8ex; border-left: 1px solid #8ae234; padding-left: 1ex;\">three<br /><blockquote class=\"gmail_quote\" style=\"margin: 0pt 0pt 1ex 0.8ex; border-left: 1px solid #fcaf3e; padding-left: 1ex;\">four<br /><blockquote class=\"gmail_quote\" style=\"margin: 0pt 0pt 1ex 0.8ex; border-left: 1px solid #e9b96e; padding-left: 1ex;\">five<br /><blockquote class=\"gmail_quote\" style=\"margin: 0pt 0pt 1ex 0.8ex; border-left: 1px solid #ccc; padding-left: 1ex;\">six</blockquote></blockquote></blockquote></blockquote></blockquote></blockquote></pre>", result);
        assertEquals("<pre class=\"k9mail\">"
                + "zero<br />"
                + "<blockquote class=\"gmail_quote\" style=\"margin: 0pt 0pt 1ex 0.8ex; border-left: 1px solid #729fcf; padding-left: 1ex;\">"
                +   " one<br />"
                +   "<blockquote class=\"gmail_quote\" style=\"margin: 0pt 0pt 1ex 0.8ex; border-left: 1px solid #ad7fa8; padding-left: 1ex;\">"
                +     " two<br />"
                +     "<blockquote class=\"gmail_quote\" style=\"margin: 0pt 0pt 1ex 0.8ex; border-left: 1px solid #8ae234; padding-left: 1ex;\">"
                +       " three<br />"
                +       "<blockquote class=\"gmail_quote\" style=\"margin: 0pt 0pt 1ex 0.8ex; border-left: 1px solid #fcaf3e; padding-left: 1ex;\">"
                +         " four<br />"
                +         "<blockquote class=\"gmail_quote\" style=\"margin: 0pt 0pt 1ex 0.8ex; border-left: 1px solid #e9b96e; padding-left: 1ex;\">"
                +           " five<br />"
                +           "<blockquote class=\"gmail_quote\" style=\"margin: 0pt 0pt 1ex 0.8ex; border-left: 1px solid #ccc; padding-left: 1ex;\">"
                +             " six"
                +           "</blockquote>"
                +         "</blockquote>"
                +       "</blockquote>"
                +     "</blockquote>"
                +   "</blockquote>"
                + "</blockquote>"
                + "</pre>", result);
    }

    private void writeToFile(final String content) {
@@ -83,4 +134,37 @@ public class HtmlConverterTest extends TestCase {
            e.printStackTrace();
        }
    }

    public void testPreserveSpacesAtFirst() {
        String message = "foo\n"
                + " bar\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"
                + "  > \n";
        String result = HtmlConverter.textToHtml(message);
        writeToFile(result);
        assertEquals("<pre class=\"k9mail\">"
                + " <br />"
                + "  &amp;<br />"
                + "    <br />"
                + "   &lt;<br />"
                + "<blockquote class=\"gmail_quote\" style=\"margin: 0pt 0pt 1ex 0.8ex; border-left: 1px solid #729fcf; padding-left: 1ex;\">"
                + " <br />"
                + "</blockquote>"
                + "</pre>", result);
    }
}