commit c3c04b3359b7beb9e831a190b3ab2cbc222a3df3
parent 6f4813a0242ef6a25f3cb1298029513e187be320
Author: Jan Dankert <devnull@localhost>
Date: Wed, 10 Oct 2012 00:01:28 +0200
Neuer BBCodeConverter.
Diffstat:
4 files changed, 206 insertions(+), 562 deletions(-)
diff --git a/src/BBCodeTest.java b/src/BBCodeTest.java
@@ -0,0 +1,41 @@
+import de.mtbnews.android.adapter.BBCodeConverter;
+import junit.framework.TestCase;
+
+public class BBCodeTest extends TestCase
+{
+ public void testQuote() throws Exception
+ {
+
+ String in = "[quotE=Schrott]Hallo[/Quote]Hallo [B]Du[/b].";
+ String out = "<blockquote>Hallo</blockquote>Hallo <b>Du</b>.";
+ testInOut(in, out);
+ }
+
+ public void testLink() throws Exception
+ {
+
+ String in = "[url]http://example.com/image.png[/url].";
+ String out = "<a href=\"http://example.com/image.png\">http://example.com/image.png</a>.";
+ testInOut(in, out);
+
+ in = "[url=http://example.com/image.png]haha[/url].";
+ out = "<a href=\"http://example.com/image.png\">haha</a>.";
+ testInOut(in, out);
+ }
+
+ public void testImage() throws Exception
+ {
+
+ String in = "[img]http://example.com/image.png[/imG].";
+ String out = "<a href=\"http://example.com/image.png\">Bild anzeigen</a>.";
+ testInOut(in, out);
+ }
+
+
+ private void testInOut(String in, String out) throws Exception
+ {
+ BBCodeConverter bbCodeConverter = new BBCodeConverter();
+ String processed = bbCodeConverter.process(in);
+ assertEquals(out, processed);
+ }
+}
diff --git a/src/de/mtbnews/android/adapter/BBCodeConverter.java b/src/de/mtbnews/android/adapter/BBCodeConverter.java
@@ -0,0 +1,148 @@
+package de.mtbnews.android.adapter;
+
+import java.util.regex.Pattern;
+
+import de.mtbnews.android.util.IBC;
+
+/**
+ * @author Jan Dankert
+ */
+public class BBCodeConverter
+{
+ private static final String CR_LF = "(?:\r\n|\r|\n)?";
+
+ /** */
+ private boolean acceptHTML = false;
+
+ /** */
+ private boolean acceptBBCode = true;
+
+ /**
+ * @param acceptBBCode
+ * the new acceptBBCode value
+ */
+ public void setAcceptBBCode(boolean acceptBBCode)
+ {
+ this.acceptBBCode = acceptBBCode;
+ }
+
+ /**
+ * @param acceptHTML
+ * the new acceptHTML value
+ */
+ public void setAcceptHTML(boolean acceptHTML)
+ {
+ this.acceptHTML = acceptHTML;
+ }
+
+ /**
+ * @param string
+ * @return HTML-formated message
+ */
+ public String process(String string)
+ {
+ string = string.replaceAll("(\r\n|\n\r|\n|\r)", "<br />");
+
+ string = processTag(string,
+ "\\[color=['\"]?(.*?[^'\"])['\"]?\\](.*?)\\[/color\\]",
+ "<span style='color:$1'>$2</span>");
+
+ string = processTag(string, "\\[quote.*\\](.*?)\\[/quote\\]",
+ "<blockquote>$1</blockquote>");
+
+ string = processTag(string,
+ "\\[list=['\"]?(.*?[^'\"])['\"]?\\](.*?)\\[/list\\]",
+ "<ul>$2</ul>");
+
+ // str = str.replaceAll("(\r\n|\n\r|\n|\r)", "<br>");
+
+ // [color]
+ // [size]
+ string = processTag(string,
+ "\\[size=['\"]?([0-9]|[1-2][0-9])['\"]?\\](.*?)\\[/size\\]",
+ "<span style='font-size:$1px'>$2</span>");
+
+ string = processTag(string,
+ "\\[mention=['\"]?([0-9]+)['\"]?\\](.*?)\\[/mention\\]",
+ "<a href=\"" + IBC.IBC_FORUM_URL + "member.php?u=$1\">→$2</a>");
+
+ // [b][u][i]
+ string = processTag(string, "\\[b\\](.*?)\\[/b\\]", "<b>$1</b>");
+ string = processTag(string, "\\[u\\](.*?)\\[/u\\]", "<u>$1</u>");
+ string = processTag(string, "\\[i\\](.*?)\\[/i\\]", "<i>$1</i>");
+
+ // Smileys (very poor implementation)
+ string = processTag(string, ":daumen:", "+1");
+ string = processTag(string, ":love:", "♥");
+ string = processTag(string, "[*]", "•");
+
+ // [img]
+ string = processTag(string, "\\[img\\](.*?)\\[/img\\]",
+ "<a href=\"$1\">Bild anzeigen</a>");
+
+ // [url]
+ string = processTag(string, "\\[url\\](.*?)\\[/url\\]",
+ "<a href=\"$1\">$1</a>");
+ string = processTag(string,
+ "\\[url=['\"]?(.*?[^'\"])['\"]?\\](.*?)\\[/url\\]",
+ "<a href=\"$1\">$2</a>");
+ string = processTag(string,
+ "\\[yt.*\\](.*?)\\[/yt\\]",
+ "<a href=\"http://www.youtube.com/watch?v=$2\">Video bei Youtube anzeigen</a>");
+
+ // [email]
+ string = processTag(string, "\\[email\\](.*?)\\[/email\\]",
+ "<a href='mailto:$1'>$1</a>");
+
+ return string;
+ }
+
+ private static String processTag(String text, String pattern,
+ String replaceWith)
+ {
+ return Pattern.compile(pattern, Pattern.CASE_INSENSITIVE).matcher(text)
+ .replaceAll(replaceWith);
+ }
+
+ /**
+ * @param content
+ * @return -
+ */
+ private static String escapeBBcode(String content)
+ {
+ // escaping single characters
+ content = content.replaceAll("[", "[");
+ content = content.replaceAll("]", "]");
+ content = content.replaceAll("\t", " ");
+
+ // taking off start and end line breaks
+ content = content.replaceAll("\\A\r\n|\\A\r|\\A\n|\r\n\\z|\r\\z|\n\\z",
+ "");
+
+ // replacing spaces for to keep indentation
+ content = content.replaceAll(" ", " ");
+ content = content.replaceAll(" ", " ");
+
+ return content;
+ }
+
+ /**
+ * @param content
+ * @return -
+ */
+ private static String escapeHtml(String content)
+ {
+ // escaping single characters
+ content = content.replaceAll("&", "&");
+ content = content.replaceAll("<", "<");
+ content = content.replaceAll(">", ">");
+
+ // replacing line breaks for <br>
+ // content = content.replaceAll("\r\n", "<br>");
+ // content = replaceAll(content, "\n\r".toCharArray(), new String[] {
+ // "<br>", "<br>" });
+
+ return content;
+ }
+
+}
diff --git a/src/de/mtbnews/android/adapter/ListEntryContentAdapter.java b/src/de/mtbnews/android/adapter/ListEntryContentAdapter.java
@@ -11,6 +11,7 @@ import android.content.SharedPreferences;
import android.graphics.Typeface;
import android.text.Html;
import android.text.format.DateFormat;
+import android.text.method.LinkMovementMethod;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -18,7 +19,6 @@ import android.widget.BaseAdapter;
import android.widget.TextView;
import de.mtbnews.android.IBCApplication;
import de.mtbnews.android.R;
-import de.mtbnews.android.image.URLImageParser;
import de.mtbnews.android.tapatalk.wrapper.ListEntry;
/**
@@ -157,25 +157,27 @@ public class ListEntryContentAdapter extends BaseAdapter
// .create();
// html = create.process(e.getContent());
html = e.getContent();
- html = new ProcessBBCode().preparePostText(html);
-
- Html.ImageGetter imageGetter = null;
- if (prefs.getBoolean("load_images", false))
- // imageGetter = new ImageGetter();
- imageGetter = new URLImageParser(viewHolder.desc, mContext);
-
- viewHolder.desc.setText(Html.fromHtml(html.toString(),
- imageGetter, null));
+ html = new BBCodeConverter().process(html);
+
+ // Html.ImageGetter imageGetter = null;
+ // if (prefs.getBoolean("load_images", false))
+ // // imageGetter = new ImageGetter();
+ // imageGetter = new URLImageParser(viewHolder.desc, mContext);
+
+ // viewHolder.desc.setText(Html.fromHtml(html.toString(),
+ // imageGetter, null));
+ viewHolder.desc.setText(Html.fromHtml(html));
+ viewHolder.desc.setMovementMethod(LinkMovementMethod.getInstance());
+ //viewHolder.desc.setAutoLinkMask(Linkify.ALL);
}
else if (containsHtml)
{
+
final CharSequence html = e.getContent();
- Html.ImageGetter imageGetter = null;
- if (prefs.getBoolean("load_images", false))
- imageGetter = new URLImageParser(viewHolder.desc, mContext);
+ // if (prefs.getBoolean("load_images", false))
+ // imageGetter = new URLImageParser(viewHolder.desc, mContext);
- viewHolder.desc.setText(Html.fromHtml(html.toString(),
- imageGetter, null));
+ viewHolder.desc.setText(Html.fromHtml(html.toString()));
}
else
{
diff --git a/src/de/mtbnews/android/adapter/ProcessBBCode.java b/src/de/mtbnews/android/adapter/ProcessBBCode.java
@@ -1,547 +0,0 @@
-package de.mtbnews.android.adapter;
-
-import java.io.Serializable;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.Set;
-import java.util.Stack;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/*
- * Copyright 2004 JavaFree.org
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * $Id: ProcessBBCode.java,v 1.18.2.2.4.5 2008/10/07 23:06:16 daltoncamargo Exp
- * $
- *
- * @author Dalton Camargo - <a href="mailto:dalton@javabb.org">dalton@javabb.org
- * </a> <br>
- * @author Ronald Tetsuo Miura
- */
-public class ProcessBBCode implements Serializable
-{
- /**
- *
- */
- private static final long serialVersionUID = 1L;
-
- private static final String CR_LF = "(?:\r\n|\r|\n)?";
-
- /** */
- private boolean acceptHTML = false;
-
- /** */
- private boolean acceptBBCode = true;
-
- /**
- * @return acceptBBCode
- */
- public boolean getAcceptBBCode()
- {
- return acceptBBCode;
- }
-
- /**
- * @param acceptBBCode
- * the new acceptBBCode value
- */
- public void setAcceptBBCode(boolean acceptBBCode)
- {
- this.acceptBBCode = acceptBBCode;
- }
-
- /**
- * @return htmlAccepted
- */
- public boolean getAcceptHTML()
- {
- return acceptHTML;
- }
-
- /**
- * @param acceptHTML
- * the new acceptHTML value
- */
- public void setAcceptHTML(boolean acceptHTML)
- {
- this.acceptHTML = acceptHTML;
- }
-
- /**
- * @param texto
- * @return TODO unuseful parameters.
- */
- public String preparePostText(String texto)
- {
- if (!getAcceptHTML())
- {
- texto = escapeHtml(texto);
- }
- if (getAcceptBBCode())
- {
- texto = process(texto);
- }
- return texto;
- }
-
- /**
- * @param string
- * @return HTML-formated message
- */
- private String process(String string)
- {
- string = string.replaceAll("(\r\n|\n\r|\n|\r)", "<br>");
-
- StringBuffer buffer = new StringBuffer(string);
- processCode(buffer);
-
- /*
- * processNestedTags( buffer, "quote",
- * "<table width='90%' cellspacing='1' cellpadding='1' border='0' " +
- * "align='center'><tr><td><span class='genmed'><b>{BBCODE_PARAM}:</b></span></td></tr></table><table width='90%' cellspacing='1' cellpadding='1' border='0' align='center'><tr><td class='quote' bgcolor='#F3F5FF'>"
- * , " </td></tr></table>",
- * "<table width='90%' cellspacing='1' cellpadding='3' border='0' " +
- * "align='center'><tr><td><span class='genmed'><b>Quote:</b></span></td></tr><tr><td class='quote'>"
- * , " </td></tr></table>", "[*]", false, true, true);
- */
-
- processNestedTags(
- buffer,
- "quote",
- "</p><blockquote><div class='term'><b>{BBCODE_PARAM}:</b></div><div class='definition'><div><div>",
- "</div></div></div></blockquote><p>",
- "</p><blockquote><div class='term'><b>Quote:</b></div><div class='definition'><div><div>",
- " </div></div></div></blockquote><p>", "[*]", false, true, true);
-
- processNestedTags(buffer, "list", "<ol type=\"{BBCODE_PARAM}\">",
- "</ol>", "<ul>", "</ul>", "<li>", true, true, true);
-
- String str = buffer.toString();
-
- // str = str.replaceAll("(\r\n|\n\r|\n|\r)", "<br>");
-
- // [color]
- str = str.replaceAll(
- "\\[color=['\"]?(.*?[^'\"])['\"]?\\](.*?)\\[/color\\]",
- "<span style='color:$1'>$2</span>");
-
- // [size]
- str = str.replaceAll(
- "\\[size=['\"]?([0-9]|[1-2][0-9])['\"]?\\](.*?)\\[/size\\]",
- "<span style='font-size:$1px'>$2</span>");
-
- // [b][u][i]
- str = str.replaceAll("\\[b\\](.*?)\\[/b\\]", "<b>$1</b>");
- str = str.replaceAll("\\[u\\](.*?)\\[/u\\]", "<u>$1</u>");
- str = str.replaceAll("\\[i\\](.*?)\\[/i\\]", "<i>$1</i>");
-
- // [img]
- str = str.replaceAll("\\[img\\](.*?)\\[/img\\]",
- "<img src='$1' border='0' alt='0'>");
-
- // [url]
- str = str.replaceAll("\\[url\\](.*?)\\[/url\\]",
- "<a href='$1' target='_blank'>$1</a>");
- str = str.replaceAll(
- "\\[url=['\"]?(.*?[^'\"])['\"]?\\](.*?)\\[/url\\]",
- "<a href=\"$1\" target=\"_new\">$2</a>");
-
- // [email]
- str = str.replaceAll("\\[email\\](.*?)\\[/email\\]",
- "<a href='mailto:$1'>$1</a>");
-
- return str;
- }
-
- private static void processCode(StringBuffer buffer)
- {
- int start = buffer.indexOf("[code]");
- int end;
-
- for (; (start >= 0) && (start < buffer.length()); start = buffer
- .indexOf("[code]", end))
- {
-
- end = buffer.indexOf("[/code]", start);
-
- if (end < 0)
- {
- break;
- }
-
- end += "[/code]".length();
-
- String content = buffer.substring(start + "[code]".length(), end
- - "[/code]".length());
- content = escapeBBcode(content);
-
- /*
- * String replacement = "<!-- [ -code- ] --></span>" // +
- * "<table width='90%' cellspacing='1' cellpadding='3' border='0' align='center'>"
- * + "<tr><td><span class='genmed'><b>Code:</b></span></td></tr>" +
- * "<tr><td class='code'>" + content +
- * "</td></tr></table><span class='postbody'><!-- [/ -code- ] -->";
- */
-
- content = content.replaceAll("<br>", "\n");
-
- String replacement = "<!-- [ -code- ] -->" //
- + "<textarea name=\"code\" id=\"code\" class=\"java:nocontrols:nogutter\" rows=\"15\" cols=\"100\">"
- + content + "</textarea><!-- [/ -code- ] -->";
-
- /*
- * String replacement = "</span>" // +
- * "<!-- [ -code- ] --><pre class=\"brush: java;\">" + content +
- * "</pre><span class='postbody'><!-- [/ -code- ] -->";
- */
-
- buffer.replace(start, end, replacement);
-
- end = start + replacement.length();
- }
- }
-
- /**
- * @param content
- * @return -
- */
- public static String escapeBBcode(String content)
- {
- // escaping single characters
- content = replaceAll(content, "[]\t".toCharArray(), new String[] {
- "[", "]", " " });
-
- // taking off start and end line breaks
- content = content.replaceAll("\\A\r\n|\\A\r|\\A\n|\r\n\\z|\r\\z|\n\\z",
- "");
-
- // replacing spaces for to keep indentation
- content = content.replaceAll(" ", " ");
- content = content.replaceAll(" ", " ");
-
- return content;
- }
-
- /**
- * @param content
- * @return -
- */
- private static String escapeHtml(String content)
- {
- // escaping single characters
- content = replaceAll(content, "&<>".toCharArray(), new String[] {
- "&", "<", ">" });
-
- // replacing line breaks for <br>
- // content = content.replaceAll("\r\n", "<br>");
- // content = replaceAll(content, "\n\r".toCharArray(), new String[] {
- // "<br>", "<br>" });
-
- return content;
- }
-
- private static String replaceAll(String str, char[] chars,
- String[] replacement)
- {
-
- StringBuffer buffer = new StringBuffer();
- for (int i = 0; i < str.length(); i++)
- {
- char c = str.charAt(i);
- boolean matched = false;
- for (int j = 0; j < chars.length; j++)
- {
- if (c == chars[j])
- {
- buffer.append(replacement[j]);
- matched = true;
- }
- }
- if (!matched)
- {
- buffer.append(c);
- }
- }
- return buffer.toString();
- }
-
- /**
- * @param buffer
- * @param tagName
- * @param openSubstWithParam
- * @param closeSubstWithParam
- * @param openSubstWithoutParam
- * @param closeSubstWithoutParam
- * @param internalSubst
- * @param processInternalTags
- * @param acceptParam
- * @param requiresQuotedParam
- */
- private static void processNestedTags(StringBuffer buffer, String tagName,
- String openSubstWithParam, String closeSubstWithParam,
- String openSubstWithoutParam, String closeSubstWithoutParam,
- String internalSubst, boolean processInternalTags,
- boolean acceptParam, boolean requiresQuotedParam)
- {
- String str = buffer.toString();
-
- Stack openStack = new Stack();
- Set subsOpen = new HashSet();
- Set subsClose = new HashSet();
- Set subsInternal = new HashSet();
-
- String openTag = CR_LF
- + "\\["
- + tagName
- + (acceptParam ? (requiresQuotedParam ? "(?:=\"(.*?)\")?"
- : "(?:=\"?(.*?)\"?)?") : "") + "\\]" + CR_LF;
- String closeTag = CR_LF + "\\[/" + tagName + "\\]" + CR_LF;
- String internTag = CR_LF + "\\[\\*\\]" + CR_LF;
-
- String patternString = "(" + openTag + ")|(" + closeTag + ")";
-
- if (processInternalTags)
- {
- patternString += "|(" + internTag + ")";
- }
-
- Pattern tagsPattern = Pattern.compile(patternString);
- Matcher matcher = tagsPattern.matcher(str);
-
- int openTagGroup;
- int paramGroup;
- int closeTagGroup;
- int internalTagGroup;
-
- if (acceptParam)
- {
- openTagGroup = 1;
- paramGroup = 2;
- closeTagGroup = 3;
- internalTagGroup = 4;
- }
- else
- {
- openTagGroup = 1;
- paramGroup = -1; // INFO
- closeTagGroup = 2;
- internalTagGroup = 3;
- }
-
- while (matcher.find())
- {
- int length = matcher.end() - matcher.start();
- MutableCharSequence matchedSeq = new MutableCharSequence(str,
- matcher.start(), length);
-
- // test opening tags
- if (matcher.group(openTagGroup) != null)
- {
- if (acceptParam && (matcher.group(paramGroup) != null))
- {
- matchedSeq.param = matcher.group(paramGroup);
- }
-
- openStack.push(matchedSeq);
-
- // test closing tags
- }
- else if ((matcher.group(closeTagGroup) != null)
- && !openStack.isEmpty())
- {
- MutableCharSequence openSeq = (MutableCharSequence) openStack
- .pop();
-
- if (acceptParam)
- {
- matchedSeq.param = openSeq.param;
- }
-
- subsOpen.add(openSeq);
- subsClose.add(matchedSeq);
-
- // test internal tags
- }
- else if (processInternalTags
- && (matcher.group(internalTagGroup) != null)
- && (!openStack.isEmpty()))
- {
- subsInternal.add(matchedSeq);
- }
- else
- {
- // assert (false);
- }
- }
-
- LinkedList subst = new LinkedList();
- subst.addAll(subsOpen);
- subst.addAll(subsClose);
- subst.addAll(subsInternal);
-
- Collections.sort(subst, new Comparator()
- {
- public int compare(Object o1, Object o2)
- {
- MutableCharSequence s1 = (MutableCharSequence) o1;
- MutableCharSequence s2 = (MutableCharSequence) o2;
- return -(s1.start - s2.start);
- }
- });
-
- buffer.delete(0, buffer.length());
-
- int start = 0;
-
- while (!subst.isEmpty())
- {
- MutableCharSequence seq = (MutableCharSequence) subst.removeLast();
- buffer.append(str.substring(start, seq.start));
-
- if (subsClose.contains(seq))
- {
- if (seq.param != null)
- {
- buffer.append(closeSubstWithParam);
- }
- else
- {
- buffer.append(closeSubstWithoutParam);
- }
- }
- else if (subsInternal.contains(seq))
- {
- buffer.append(internalSubst);
- }
- else if (subsOpen.contains(seq))
- {
- Matcher m = Pattern.compile(openTag).matcher(
- str.substring(seq.start, seq.start + seq.length));
-
- if (m.matches())
- {
- if (acceptParam && (seq.param != null))
- {
- buffer.append( //
- openSubstWithParam.replaceAll(
- "\\{BBCODE_PARAM\\}", seq.param
- .replaceAll("\\$", "")));
- }
- else
- {
- buffer.append(openSubstWithoutParam);
- }
- }
- }
-
- start = seq.start + seq.length;
- }
-
- buffer.append(str.substring(start));
- }
-
- static class MutableCharSequence implements CharSequence
- {
- /** */
- public CharSequence base;
-
- /** */
- public int start;
-
- /** */
- public int length;
-
- /** */
- public String param = null;
-
- /**
- */
- public MutableCharSequence()
- {
- //
- }
-
- /**
- * @param base
- * @param start
- * @param length
- */
- public MutableCharSequence(CharSequence base, int start, int length)
- {
- reset(base, start, length);
- }
-
- /**
- * @see java.lang.CharSequence#length()
- */
- public int length()
- {
- return this.length;
- }
-
- /**
- * @see java.lang.CharSequence#charAt(int)
- */
- public char charAt(int index)
- {
- return this.base.charAt(this.start + index);
- }
-
- /**
- * @see java.lang.CharSequence#subSequence(int, int)
- */
- public CharSequence subSequence(int pStart, int end)
- {
- return new MutableCharSequence(this.base, this.start + pStart,
- this.start + (end - pStart));
- }
-
- /**
- * @param pBase
- * @param pStart
- * @param pLength
- * @return -
- */
- public CharSequence reset(CharSequence pBase, int pStart, int pLength)
- {
- this.base = pBase;
- this.start = pStart;
- this.length = pLength;
-
- return this;
- }
-
- /**
- * @see java.lang.Object#toString()
- */
- public String toString()
- {
- StringBuffer sb = new StringBuffer();
-
- for (int i = this.start; i < (this.start + this.length); i++)
- {
- sb.append(this.base.charAt(i));
- }
-
- return sb.toString();
- }
-
- }
-
-}