initial contribution
authoraxelcl <axelcl>
Fri, 24 Dec 2004 11:11:14 +0000 (11:11 +0000)
committeraxelcl <axelcl>
Fri, 24 Dec 2004 11:11:14 +0000 (11:11 +0000)
27 files changed:
archive/org.plog4u.wiki/.classpath [new file with mode: 0644]
archive/org.plog4u.wiki/.project [new file with mode: 0644]
archive/org.plog4u.wiki/src/META-INF/services/org.radeox.filter.Filter [new file with mode: 0644]
archive/org.plog4u.wiki/src/META-INF/services/org.radeox.macro.Macro [new file with mode: 0644]
archive/org.plog4u.wiki/src/META-INF/services/org.radeox.macro.code.SourceCodeFormatter [new file with mode: 0644]
archive/org.plog4u.wiki/src/META-INF/services/org.radeox.macro.list.ListFormatter [new file with mode: 0644]
archive/org.plog4u.wiki/src/META-INF/services/org.radeox.macro.table.Function [new file with mode: 0644]
archive/org.plog4u.wiki/src/org/plog4u/wiki/filter/FilterUtil.java [new file with mode: 0644]
archive/org.plog4u.wiki/src/org/plog4u/wiki/filter/IBodyTagSupportMacro.java [new file with mode: 0644]
archive/org.plog4u.wiki/src/org/plog4u/wiki/filter/ICachableMacro.java [new file with mode: 0644]
archive/org.plog4u.wiki/src/org/plog4u/wiki/filter/INoParserBodyFilterMacro.java [new file with mode: 0644]
archive/org.plog4u.wiki/src/org/plog4u/wiki/filter/IRenderResultMacro.java [new file with mode: 0644]
archive/org.plog4u.wiki/src/org/plog4u/wiki/filter/IWikipediaFilterConstants.java [new file with mode: 0644]
archive/org.plog4u.wiki/src/org/plog4u/wiki/filter/WikipediaFilter.java [new file with mode: 0644]
archive/org.plog4u.wiki/src/org/plog4u/wiki/filter/WikipediaParser.java [new file with mode: 0644]
archive/org.plog4u.wiki/src/org/plog4u/wiki/macro/CodeMacro.java [new file with mode: 0644]
archive/org.plog4u.wiki/src/org/plog4u/wiki/macro/HMathMacro.java [new file with mode: 0644]
archive/org.plog4u.wiki/src/org/plog4u/wiki/macro/LinkMacro.java [new file with mode: 0644]
archive/org.plog4u.wiki/src/org/plog4u/wiki/macro/MacroListMacro.java [new file with mode: 0644]
archive/org.plog4u.wiki/src/org/plog4u/wiki/macro/QuoteMacro.java [new file with mode: 0644]
archive/org.plog4u.wiki/src/org/plog4u/wiki/macro/code/AbstractCPPBasedCodeFilter.java [new file with mode: 0644]
archive/org.plog4u.wiki/src/org/plog4u/wiki/macro/code/CHashCodeFilter.java [new file with mode: 0644]
archive/org.plog4u.wiki/src/org/plog4u/wiki/macro/code/JavaCodeFilter.java [new file with mode: 0644]
archive/org.plog4u.wiki/src/org/plog4u/wiki/macro/code/NullCodeFilter.java [new file with mode: 0644]
archive/org.plog4u.wiki/src/org/plog4u/wiki/macro/code/PHPCodeFilter.java [new file with mode: 0644]
archive/org.plog4u.wiki/src/org/plog4u/wiki/macro/code/SqlCodeFilter.java [new file with mode: 0644]
archive/org.plog4u.wiki/src/org/plog4u/wiki/macro/code/XmlCodeFilter.java [new file with mode: 0644]

diff --git a/archive/org.plog4u.wiki/.classpath b/archive/org.plog4u.wiki/.classpath
new file mode 100644 (file)
index 0000000..2d5831a
--- /dev/null
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+       <classpathentry kind="src" path="src"/>
+       <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+       <classpathentry kind="lib" path="/net.sourceforge.phpeclipse.wiki/lib/radeox.jar"/>
+       <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/archive/org.plog4u.wiki/.project b/archive/org.plog4u.wiki/.project
new file mode 100644 (file)
index 0000000..b2ea3ad
--- /dev/null
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+       <name>org.plog4u.wiki</name>
+       <comment></comment>
+       <projects>
+       </projects>
+       <buildSpec>
+               <buildCommand>
+                       <name>org.eclipse.jdt.core.javabuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+       </buildSpec>
+       <natures>
+               <nature>org.eclipse.jdt.core.javanature</nature>
+       </natures>
+</projectDescription>
diff --git a/archive/org.plog4u.wiki/src/META-INF/services/org.radeox.filter.Filter b/archive/org.plog4u.wiki/src/META-INF/services/org.radeox.filter.Filter
new file mode 100644 (file)
index 0000000..82f22c4
--- /dev/null
@@ -0,0 +1,4 @@
+org.plog4u.wiki.filter.WikipediaFilter\r
+#org.radeox.filter.BoldFilter\r
+#org.radeox.filter.ItalicFilter\r
\ No newline at end of file
diff --git a/archive/org.plog4u.wiki/src/META-INF/services/org.radeox.macro.Macro b/archive/org.plog4u.wiki/src/META-INF/services/org.radeox.macro.Macro
new file mode 100644 (file)
index 0000000..00e351e
--- /dev/null
@@ -0,0 +1 @@
+org.plog4u.wiki.macro.CodeMacro
\ No newline at end of file
diff --git a/archive/org.plog4u.wiki/src/META-INF/services/org.radeox.macro.code.SourceCodeFormatter b/archive/org.plog4u.wiki/src/META-INF/services/org.radeox.macro.code.SourceCodeFormatter
new file mode 100644 (file)
index 0000000..ab7545e
--- /dev/null
@@ -0,0 +1,8 @@
+#org.snipsnap.render.macro.code.Java2HtmlCodeFilter
+org.plog4u.wiki.macro.code.CHashCodeFilter
+org.plog4u.wiki.macro.code.JavaCodeFilter
+org.plog4u.wiki.macro.code.PHPCodeFilter
+org.plog4u.wiki.macro.code.SqlCodeFilter
+org.plog4u.wiki.macro.code.XmlCodeFilter 
+org.plog4u.wiki.macro.code.NullCodeFilter
+#org.snipsnap.render.macro.code.Java2HtmlCodeFilter
diff --git a/archive/org.plog4u.wiki/src/META-INF/services/org.radeox.macro.list.ListFormatter b/archive/org.plog4u.wiki/src/META-INF/services/org.radeox.macro.list.ListFormatter
new file mode 100644 (file)
index 0000000..6636c1a
--- /dev/null
@@ -0,0 +1,5 @@
+# default list formatter\r
+org.radeox.macro.list.SimpleList\r
+org.radeox.macro.list.AtoZListFormatter\r
+org.radeox.macro.list.ExampleListFormatter\r
+org.radeox.macro.list.CollationListFormatter\r
diff --git a/archive/org.plog4u.wiki/src/META-INF/services/org.radeox.macro.table.Function b/archive/org.plog4u.wiki/src/META-INF/services/org.radeox.macro.table.Function
new file mode 100644 (file)
index 0000000..42bf41b
--- /dev/null
@@ -0,0 +1,5 @@
+# all default macros
+org.radeox.macro.table.SumFunction
+org.radeox.macro.table.AvgFunction
+org.radeox.macro.table.MaxFunction
+org.radeox.macro.table.MinFunction
diff --git a/archive/org.plog4u.wiki/src/org/plog4u/wiki/filter/FilterUtil.java b/archive/org.plog4u.wiki/src/org/plog4u/wiki/filter/FilterUtil.java
new file mode 100644 (file)
index 0000000..8fbe0ed
--- /dev/null
@@ -0,0 +1,106 @@
+package org.plog4u.wiki.filter;
+
+import java.util.List;
+import java.io.IOException;
+import java.io.Writer;
+import java.util.Arrays;
+
+public class FilterUtil {
+  public static String getImageRoot() {
+    return "theme/images";
+  }
+
+  public static String getSpaceRoot() {
+    return "space";
+  }
+
+  public static String getExecRoot() {
+    return "exec";
+  }
+
+  public static String getCommentsRoot() {
+    return "comments";
+  }
+
+  private static List extensions = Arrays.asList(new String[] { "png", "jpg", "jpeg", "gif" });
+
+  public static String normalizeServerImageName(String wikiLink) {
+    wikiLink = wikiLink.replaceAll(":", "/");
+    return wikiLink.replaceAll(" ", "_");
+  }
+
+  public static String createServerImage(String location, String name, String extension, boolean createHTMLLevel, int level) {
+    StringBuffer filename = new StringBuffer();
+    if (location != null) {
+      filename.append(location);
+      filename.append("/");
+    }
+    String normalized = normalizeServerImageName(name);
+
+    if (location == null && createHTMLLevel) {
+      for (int i = 0; i < level; i++) {
+        filename.append("../");
+      }
+    }
+
+    filename.append(normalized);
+    if (!normalized.startsWith("Image/") && extension != null) {
+      filename.append(".");
+      filename.append(extension);
+    }
+    return filename.toString();
+  }
+
+  public static String createServerImage(String location, String name, String extension) {
+    return createServerImage(location, name, extension, false, 0);
+  }
+
+  public static String createHTMLLink(String location, String name, String extension, boolean createHTMLLevel, int level) {
+    StringBuffer filename = new StringBuffer();
+    if (location != null) {
+        filename.append(location);
+        filename.append("/");
+    }
+//    System.out.println(filename);
+    String normalized = FilterUtil.normalizeWikiLink(name);
+
+    if (location == null && createHTMLLevel) {
+      for (int i = 0; i < level; i++) {
+        filename.append("../");
+      }
+    }
+
+    filename.append(normalized);
+    if (!normalized.startsWith("Image/")) {
+      filename.append(".");
+      filename.append(extension); 
+    }
+    return filename.toString();
+  }
+
+  public static String createHTMLLink(String location, String name, String extension) {
+    return createHTMLLink(location, name, extension, false, 0);
+  }
+
+  public static String normalizeWikiLink(String wikiLink) {
+    if (wikiLink.length() > 0) {
+      int index = wikiLink.lastIndexOf('/');
+      if (index >= 0) {
+        if (wikiLink.length() == index + 1) {
+          wikiLink = wikiLink.substring(0, index + 1) + wikiLink.substring(index + 1, 1).toUpperCase();
+        } else if (wikiLink.length() > index + 1) {
+          wikiLink = wikiLink.substring(0, index + 1) + wikiLink.substring(index + 1, index + 2).toUpperCase()
+              + wikiLink.substring(index + 2);
+        }
+      } else {
+        if (wikiLink.length() > 1) {
+          wikiLink = wikiLink.substring(0, 1).toUpperCase() + wikiLink.substring(1);
+        } else {
+          wikiLink = wikiLink.substring(0, 1).toUpperCase();
+        }
+      }
+    }
+    wikiLink = wikiLink.replaceAll(":", "/");
+    return wikiLink.replaceAll(" ", "_");
+  }
+}
\ No newline at end of file
diff --git a/archive/org.plog4u.wiki/src/org/plog4u/wiki/filter/IBodyTagSupportMacro.java b/archive/org.plog4u.wiki/src/org/plog4u/wiki/filter/IBodyTagSupportMacro.java
new file mode 100644 (file)
index 0000000..a74906c
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ * Created on 27.01.2004
+ *
+ * To change the template for this generated file go to
+ * Window - Preferences - Java - Code Generation - Code and Comments
+ */
+package org.plog4u.wiki.filter;
+
+/**
+ * this interface indicates that a macro has a body content
+ */
+public interface IBodyTagSupportMacro {
+
+}
diff --git a/archive/org.plog4u.wiki/src/org/plog4u/wiki/filter/ICachableMacro.java b/archive/org.plog4u.wiki/src/org/plog4u/wiki/filter/ICachableMacro.java
new file mode 100644 (file)
index 0000000..b6e53d5
--- /dev/null
@@ -0,0 +1,8 @@
+package org.plog4u.wiki.filter;
+
+/**
+ * this interface indicates that a macro has a body content
+ */
+public interface ICachableMacro {
+
+}
diff --git a/archive/org.plog4u.wiki/src/org/plog4u/wiki/filter/INoParserBodyFilterMacro.java b/archive/org.plog4u.wiki/src/org/plog4u/wiki/filter/INoParserBodyFilterMacro.java
new file mode 100644 (file)
index 0000000..3cb773b
--- /dev/null
@@ -0,0 +1,11 @@
+package org.plog4u.wiki.filter;
+
+/**
+ * Interface that indicates, that a macro content (i.e. body) 
+ * shouldn't be filtered in ParserFilter
+ * 
+ * @see org.radeox.filter.WikipediaParser
+ */
+public interface INoParserBodyFilterMacro extends IBodyTagSupportMacro {
+
+}
diff --git a/archive/org.plog4u.wiki/src/org/plog4u/wiki/filter/IRenderResultMacro.java b/archive/org.plog4u.wiki/src/org/plog4u/wiki/filter/IRenderResultMacro.java
new file mode 100644 (file)
index 0000000..0890ab2
--- /dev/null
@@ -0,0 +1,10 @@
+package org.plog4u.wiki.filter;
+
+/**
+ * 
+ *
+ * Interface that indicates to render the result of a macro call 
+ */
+public interface IRenderResultMacro {
+
+}
diff --git a/archive/org.plog4u.wiki/src/org/plog4u/wiki/filter/IWikipediaFilterConstants.java b/archive/org.plog4u.wiki/src/org/plog4u/wiki/filter/IWikipediaFilterConstants.java
new file mode 100644 (file)
index 0000000..4aee5ed
--- /dev/null
@@ -0,0 +1,347 @@
+package org.plog4u.wiki.filter;
+
+public interface IWikipediaFilterConstants {
+  final static String[] ARGUMENTS = { "static/images" };
+  final static String[] IMAGE_STRINGS =
+    {
+      "ep",
+      "<img src=\"{0}/ep.png\" border=\"0\" alt=\"EclipseProject.de\" />",
+      "xml",
+      "<img src=\"{0}/rss-small.png\" border=\"0\" alt=\"XML\" />",
+      "note",
+      "<img src=\"{0}/note.gif\" border=\"0\" alt=\"Note\" />",
+      "tip",
+      "<img src=\"{0}/tip.gif\" border=\"0\" alt=\"Tip\" />",
+      "tryit",
+      "<img src=\"{0}/tryit.gif\" border=\"0\" alt=\"Try it!\" />",
+      "1",
+      "<img src=\"{0}/tag_1.gif\" border=\"0\" alt=\"1.\" />",
+      "2",
+      "<img src=\"{0}/tag_2.gif\" border=\"0\" alt=\"2.\" />",
+      "3",
+      "<img src=\"{0}/tag_3.gif\" border=\"0\" alt=\"3.\" />",
+      "4",
+      "<img src=\"{0}/tag_4.gif\" border=\"0\" alt=\"4.\" />",
+      "5",
+      "<img src=\"{0}/tag_5.gif\" border=\"0\" alt=\"5.\" />",
+      "6",
+      "<img src=\"{0}/tag_6.gif\" border=\"0\" alt=\"6.\" />",
+      "7",
+      "<img src=\"{0}/tag_7.gif\" border=\"0\" alt=\"7.\" />",
+      "surprised",
+      "<img src=\"{0}/icon_surprised.gif\" alt=\"Surprised\" border=\"0\" />",
+      "lol",
+      "<img src=\"{0}/icon_lol.gif\" alt=\"Laughing\" border=\"0\" />",
+      "cry",
+      "<img src=\"{0}/icon_cry.gif\" alt=\"Crying or Very sad\" border=\"0\" />",
+      "sad",
+      "<img src=\"{0}/icon_sad.gif\" alt=\"Sad\" border=\"0\" />",
+      "smile",
+      "<img src=\"{0}/icon_smile.gif\" alt=\"Smile\" border=\"0\" />",
+      "biggrin",
+      "<img src=\"{0}/icon_biggrin.gif\" alt=\"Very Happy\" border=\"0\" />",
+      "eek",
+      "<img src=\"{0}/icon_eek.gif\" alt=\"Shocked\" border=\"0\" />",
+      "confused",
+      "<img src=\"{0}/icon_confused.gif\" alt=\"Confused\" border=\"0\" />",
+      "cool",
+      "<img src=\"{0}/icon_cool.gif\" alt=\"Cool\" border=\"0\" />",
+      "mad",
+      "<img src=\"{0}/icon_mad.gif\" alt=\"Mad\" border=\"0\" />",
+      "razz",
+      "<img src=\"{0}/icon_razz.gif\" alt=\"Razz\" border=\"0\" />",
+      "redface",
+      "<img src=\"{0}/icon_redface.gif\" alt=\"Embarassed\" border=\"0\" />",
+      "evil",
+      "<img src=\"{0}/icon_evil.gif\" alt=\"Evil or Very Mad\" border=\"0\" />",
+      "twisted",
+      "<img src=\"{0}/icon_twisted.gif\" alt=\"Twisted Evil\" border=\"0\" />",
+      "rolleyes",
+      "<img src=\"{0}/icon_rolleyes.gif\" alt=\"Rolling Eyes\" border=\"0\" />",
+      "wink",
+      "<img src=\"{0}/icon_wink.gif\" alt=\"Wink\" border=\"0\" />",
+      "exclaim",
+      "<img src=\"{0}/icon_exclaim.gif\" alt=\"Exclamation\" border=\"0\" />",
+      "question",
+      "<img src=\"{0}/icon_question.gif\" alt=\"Question\" border=\"0\" />",
+      "idea",
+      "<img src=\"{0}/icon_idea.gif\" alt=\"Idea\" border=\"0\" />",
+      "arrow",
+      "<img src=\"{0}/icon_arrow.gif\" alt=\"Arrow\" border=\"0\" />",
+      "mrgreen",
+      "<img src=\"{0}/icon_mrgreen.gif\" alt=\"Mr. Green\" border=\"0\" />",
+      "neutral",
+      "<img src=\"{0}/icon_neutral.gif\" alt=\"Neutral\" border=\"0\" />",
+      };
+  final static String[] ENTITY_STRINGS =
+    {
+      "amp",
+      "lt",
+      "gt",
+      "quot",
+      "nbsp",
+      "iexcl",
+      "cent",
+      "pound",
+      "curren",
+      "yen",
+      "trade",
+      "copy",
+      "reg",
+      "euro",
+      "brvbar",
+      "brkbar",
+      "sect",
+      "uml",
+      "die",
+      "ordf",
+      "laquo",
+      "not",
+      "shy",
+      "reg",
+      "macr",
+      "hibar",
+      "deg",
+      "plusmn",
+      "sup2",
+      "sup3",
+      "acute",
+      "micro",
+      "para",
+      "middot",
+      "cedil",
+      "sup1",
+      "ordm",
+      "raquo",
+      "frac14",
+      "frac12",
+      "frac34",
+      "iquest",
+      "Agrave",
+      "Aacute",
+      "Acirc",
+      "Atilde",
+      "Auml",
+      "Aring",
+      "AElig",
+      "Ccedil",
+      "Egrave",
+      "Eacute",
+      "Ecirc",
+      "Euml",
+      "lgrave",
+      "lacute",
+      "lcirc",
+      "luml",
+      "ETH",
+      "Ntilde",
+      "Ograve",
+      "Oacute",
+      "Ocirc",
+      "Otilde",
+      "Ouml",
+      "times",
+      "Oslash",
+      "Ugrave",
+      "Uacute",
+      "Ucirc",
+      "Uuml",
+      "Yacute",
+      "THORN",
+      "szlig",
+      "agrave",
+      "aacute",
+      "acirc",
+      "atilde",
+      "auml",
+      "aring",
+      "aelig",
+      "ccedil",
+      "egrave",
+      "eacute",
+      "ecirc",
+      "euml",
+      "igrave",
+      "iacute",
+      "icirc",
+      "iuml",
+      "eth",
+      "ntilde",
+      "ograve",
+      "oacute",
+      "ocirc",
+      "otilde",
+      "ouml",
+      "divide",
+      "oslash",
+      "ugrave",
+      "uacute",
+      "ucirc",
+      "uuml",
+      "yacute",
+      "thorn",
+      "yuml",
+      "iquest",
+      "iexcl",
+      "sect",
+      "para",
+      "mdash",
+      "lsaquo",
+      "rsaquo",
+      "laquo",
+      "raquo",
+      "lsquo",
+      "rsquo",
+      "ldquo",
+      "rdquo",
+      "fnof",
+      "Alpha",
+      "Beta",
+      "Gamma",
+      "Delta",
+      "Epsilon",
+      "Zeta",
+      "Eta",
+      "Theta",
+      "Iota",
+      "Kappa",
+      "Lambda",
+      "Mu",
+      "Nu",
+      "Xi",
+      "Omicron",
+      "Pi",
+      "Rho",
+      "Sigma",
+      "Tau",
+      "Upsilon",
+      "Phi",
+      "Chi",
+      "Psi",
+      "Omega",
+      "alpha",
+      "beta",
+      "gamma",
+      "delta",
+      "epsilon",
+      "zeta",
+      "eta",
+      "theta",
+      "iota",
+      "kappa",
+      "lambda",
+      "mu",
+      "nu",
+      "xi",
+      "omicron",
+      "pi",
+      "rho",
+      "sigmaf",
+      "sigma",
+      "tau",
+      "upsilon",
+      "phi",
+      "chi",
+      "psi",
+      "omega",
+      "thetasym",
+      "upsih",
+      "piv",
+      "bull",
+      "hellip",
+      "prime",
+      "Prime",
+      "oline",
+      "frasl",
+      "weierp",
+      "image",
+      "real",
+      "trade",
+      "alefsym",
+      "larr",
+      "uarr",
+      "rarr",
+      "darr",
+      "harr",
+      "crarr",
+      "lArr",
+      "dArr",
+      "hArr",
+      "forall",
+      "part",
+      "exist",
+      "empty",
+      "nabla",
+      "isin",
+      "notin",
+      "ni",
+      "prod",
+      "sum",
+      "minus",
+      "lowast",
+      "radic",
+      "prop",
+      "infin",
+      "ang",
+      "and",
+      "or",
+      "cap",
+      "cup",
+      "int",
+      "there4",
+      "sim",
+      "cong",
+      "asymp",
+      "ne",
+      "equiv",
+      "le",
+      "ge",
+      "sub",
+      "sup",
+      "nsub",
+      "sube",
+      "supe",
+      "oplus",
+      "otimes",
+      "perp",
+      "sdot",
+      "lceil",
+      "rceil",
+      "lfloor",
+      "rfloor",
+      "lang",
+      "rang",
+      "loz",
+      "spades",
+      "clubs",
+      "hearts",
+      "diams",
+      "OElig",
+      "oelig",
+      "Scaron",
+      "scaron",
+      "Yuml",
+      "circ",
+      "tilde",
+      "ensp",
+      "emsp",
+      "thinsp",
+      "zwnj",
+      "zwj",
+      "lrm",
+      "rlm",
+      "ndash",
+      "mdash",
+      "lsquo",
+      "rsquo",
+      "sbquo",
+      "ldquo",
+      "rdquo",
+      "bdquo",
+      "dagger",
+      "Dagger",
+      "permil",
+      };
+}
+
+
diff --git a/archive/org.plog4u.wiki/src/org/plog4u/wiki/filter/WikipediaFilter.java b/archive/org.plog4u.wiki/src/org/plog4u/wiki/filter/WikipediaFilter.java
new file mode 100644 (file)
index 0000000..dc7f3ef
--- /dev/null
@@ -0,0 +1,984 @@
+package org.plog4u.wiki.filter;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.text.MessageFormat;
+import java.util.HashMap;
+import java.util.HashSet;
+
+
+import org.plog4u.wiki.filter.tags.AbstractTag;
+import org.plog4u.wiki.filter.tags.CloseTagToken;
+import org.plog4u.wiki.filter.tags.DivTag;
+import org.plog4u.wiki.filter.tags.FontTag;
+import org.plog4u.wiki.filter.tags.OpenTagToken;
+import org.plog4u.wiki.filter.tags.SpecialTagToken;
+import org.plog4u.wiki.filter.tags.TableTag;
+import org.radeox.api.engine.ImageRenderEngine;
+import org.radeox.api.engine.IncludeRenderEngine;
+import org.radeox.api.engine.RenderEngine;
+import org.radeox.api.engine.WikiRenderEngine;
+import org.radeox.filter.CacheFilter;
+import org.radeox.filter.FilterSupport;
+import org.radeox.filter.context.FilterContext;
+import org.radeox.filter.interwiki.InterWiki;
+import org.radeox.macro.Macro;
+import org.radeox.macro.MacroRepository;
+import org.radeox.macro.parameter.MacroParameter;
+import org.radeox.util.Encoder;
+import org.radeox.util.StringBufferWriter;
+
+//import org.snipsnap.app.Application;
+//import org.snipsnap.fUser.Configuration;
+//import org.snipsnap.app.Application;
+
+/**
+ * Parse the input and transform it for the most used wiki patterns
+ * 
+ * Parts of the Wiki Syntax are borrowed from Wikipedia.org and SnipSnap.org
+ * 
+ * @see org.plog4u.wiki.filter.WikipediaParser
+ */
+public class WikipediaFilter extends FilterSupport implements CacheFilter, IWikipediaFilterConstants {
+  
+  public class InvalidInputException extends Exception {  
+
+    public InvalidInputException() {
+      super();
+    }
+
+    public InvalidInputException(String s) {
+      super(s);
+    }
+  }
+
+  
+  
+//  public static class ListToken extends Token {
+//    int fLevel;
+//
+//    public ListToken(int token, int level) {
+//      super(token);
+//      fLevel = level;
+//    }
+//
+//    public int getLevel() {
+//      return fLevel;
+//    }
+//  }
+//
+//  public static class OpenTagToken extends Token {
+//    private String fTagName;
+//    private String fOpenTag;
+//
+//    public OpenTagToken(int token, String name, String openTag) {
+//      super(token);
+//      fTagName = name;
+//      fOpenTag = openTag;
+//
+//    }
+//
+//    public String getTagName() {
+//      return fTagName;
+//    }
+//
+//    public String getOpenTag() {
+//      return fOpenTag;
+//    }
+//
+//    public void setTagName(String name) {
+//      fTagName = name;
+//    }
+//
+//    public void setOpenTag(String openTag) {
+//      fOpenTag = openTag;
+//    }
+//  }
+//
+//  public static class SpecialTagToken extends OpenTagToken {
+//    public SpecialTagToken(int token, String name, String openTag) {
+//      super(token, name, openTag);
+//    }
+//  }
+//
+//  public static class CloseTagToken extends Token {
+//    private String fTagName;
+//    private String fCloseTag;
+//
+//    public CloseTagToken(int token, String name, String closeTag) {
+//      super(token);
+//      fTagName = name;
+//      fCloseTag = closeTag;
+//    }
+//
+//    public String getTagName() {
+//      return fTagName;
+//    }
+//
+//    public String getCloseTag() {
+//      return fCloseTag;
+//    }
+//
+//    public void setTagName(String name) {
+//      fTagName = name;
+//    }
+//
+//    public void setCloseTag(String closeTag) {
+//      fCloseTag = closeTag;
+//    }
+//
+//  }
+  final static String HEADER_STRINGS[] = { "=", "==", "===", "====", "=====", "======" };
+
+  final static int TokenNotFound = -2;
+  final static int TokenIgnore = -1;
+  final static int TokenSTART = 0;
+  final static int TokenEOF = 1;
+  final static int TokenERROR = 2;
+  final static int TokenBOLD = 3;
+  final static int TokenITALIC = 4;
+  final static int TokenSTRIKETHROUGH = 5;
+  final static int TokenSTRONG = 8;
+  final static int TokenEM = 9;
+
+  final static int TokenCOMMA = 134;
+
+  final static int TokenDOLLAR_LBRACE = 127;
+
+  final static int TokenLIST_UL_START = 50;
+  final static int TokenLIST_OL_START = 51;
+
+  final static int TokenLIST_UL_END = 75;
+  final static int TokenLIST_OL_END = 76;
+
+  final static int TokenHTML_BR_OPEN = 190;
+  final static int TokenHTML_HR_OPEN = 191;
+
+  final static int TokenHTML_BOLD_OPEN = 200;
+  final static int TokenHTML_BOLD_CLOSE = 201;
+  final static int TokenHTML_ITALIC_OPEN = 202;
+  final static int TokenHTML_ITALIC_CLOSE = 203;
+  final static int TokenHTML_UNDERLINE_OPEN = 204;
+  final static int TokenHTML_UNDERLINE_CLOSE = 205;
+  final static int TokenHTML_STRIKE_OPEN = 206;
+  final static int TokenHTML_STRIKE_CLOSE = 207;
+  final static int TokenHTML_PARAGRAPH_OPEN = 208;
+  final static int TokenHTML_PARAGRAPH_CLOSE = 209;
+  final static int TokenHTML_PRE_OPEN = 210;
+  final static int TokenHTML_PRE_CLOSE = 211;
+  final static int TokenHTML_BLOCKQUOTE_OPEN = 212;
+  final static int TokenHTML_BLOCKQUOTE_CLOSE = 213;
+  final static int TokenHTML_SUB_OPEN = 216;
+  final static int TokenHTML_SUB_CLOSE = 217;
+  final static int TokenHTML_SUP_OPEN = 218;
+  final static int TokenHTML_SUP_CLOSE = 219;
+
+  final static int TokenHTML_H1_CLOSE = 221;
+
+  final static int TokenHTML_H1_OPEN = 220;
+  final static int TokenHTML_H2_CLOSE = 223;
+  final static int TokenHTML_H2_OPEN = 222;
+  final static int TokenHTML_H3_CLOSE = 225;
+  final static int TokenHTML_H3_OPEN = 224;
+  final static int TokenHTML_H4_CLOSE = 227;
+  final static int TokenHTML_H4_OPEN = 226;
+  final static int TokenHTML_H5_CLOSE = 229;
+  final static int TokenHTML_H5_OPEN = 228;
+  final static int TokenHTML_H6_CLOSE = 231;
+  final static int TokenHTML_H6_OPEN = 230;
+  final static int TokenHTML_EM_OPEN = 240;
+  final static int TokenHTML_EM_CLOSE = 241;
+
+  
+  final static int TokenHTML_STRONG_OPEN = 242;
+  final static int TokenHTML_STRONG_CLOSE = 243;
+  
+  final static int TokenHTML_VAR_OPEN = 245;
+  final static int TokenHTML_VAR_CLOSE = 246;
+  final static int TokenHTML_CODE_OPEN = 247;
+  final static int TokenHTML_CODE_CLOSE = 248;
+
+  final static int TokenHTML_S_OPEN = 249;
+  final static int TokenHTML_S_CLOSE = 250;
+  final static int TokenHTML_SMALL_OPEN = 251;
+  final static int TokenHTML_SMALL_CLOSE = 252;
+  
+  final static int TokenHTML_MATH_OPEN = 400;
+  final static int TokenHTML_MATH_CLOSE = 401;
+  
+  final static int TokenHTML_TABLE_OPEN = 500;
+  final static int TokenHTML_TABLE_CLOSE = 501;
+  final static int TokenHTML_CAPTION_OPEN = 502;
+  final static int TokenHTML_CAPTION_CLOSE = 503;
+  final static int TokenHTML_TH_OPEN = 504;
+  final static int TokenHTML_TH_CLOSE = 505;
+  final static int TokenHTML_TR_OPEN = 506;
+  final static int TokenHTML_TR_CLOSE = 507;
+  final static int TokenHTML_TD_OPEN = 508;
+  final static int TokenHTML_TD_CLOSE = 509;
+  
+  final static int TokenHTML_FONT_OPEN = 520;
+  final static int TokenHTML_FONT_CLOSE = 521;
+  final static int TokenHTML_CENTER_OPEN = 522;
+  final static int TokenHTML_CENTER_CLOSE = 523;
+  final static int TokenHTML_TT_OPEN = 524;
+  final static int TokenHTML_TT_CLOSE = 525;
+  final static int TokenHTML_DIV_OPEN = 526;
+  final static int TokenHTML_DIV_CLOSE = 527;
+  
+  final static int TokenIdentifier = 138;
+  final static int TokenLBRACKET = 132;
+
+  final static int TokenLPAREN = 128;
+
+  final static int TokenPLUGIN_IDENTIFIER = 130;
+  final static int TokenRBRACE = 131;
+  final static int TokenRBRACKET = 133;
+  final static int TokenRPAREN = 129;
+
+  final static AbstractTag BOLD = new AbstractTag(TokenBOLD);
+  final static AbstractTag ITALIC = new AbstractTag(TokenITALIC);
+  final static AbstractTag STRONG = new AbstractTag(TokenSTRONG);
+  final static AbstractTag EM = new AbstractTag(TokenEM);
+
+  final static AbstractTag HTML_BR_OPEN = new SpecialTagToken(TokenHTML_BR_OPEN, "br", "<br/>");
+  final static AbstractTag HTML_HR_OPEN = new SpecialTagToken(TokenHTML_HR_OPEN, "hr", "<hr/>");
+
+  final static AbstractTag HTML_EM_CLOSE = new CloseTagToken(TokenHTML_EM_CLOSE, "em", "</i>");
+  final static AbstractTag HTML_EM_OPEN = new OpenTagToken(TokenHTML_EM_OPEN, "em", "<i>");
+  final static AbstractTag HTML_H1_CLOSE = new CloseTagToken(TokenHTML_H1_CLOSE, "h1", "</h1>");
+  final static AbstractTag HTML_H1_OPEN = new OpenTagToken(TokenHTML_H1_OPEN, "h1", "<h1>");
+  final static AbstractTag HTML_H2_CLOSE = new CloseTagToken(TokenHTML_H2_CLOSE, "h2", "</h2>");
+  final static AbstractTag HTML_H2_OPEN = new OpenTagToken(TokenHTML_H2_OPEN, "h2", "<h2>");
+  final static AbstractTag HTML_H3_CLOSE = new CloseTagToken(TokenHTML_H3_CLOSE, "h3", "</h3>");
+  final static AbstractTag HTML_H3_OPEN = new OpenTagToken(TokenHTML_H3_OPEN, "h3", "<h3>");
+  final static AbstractTag HTML_H4_CLOSE = new CloseTagToken(TokenHTML_H4_CLOSE, "h4", "</h4>");
+  final static AbstractTag HTML_H4_OPEN = new OpenTagToken(TokenHTML_H4_OPEN, "h4", "<h4>");
+  final static AbstractTag HTML_H5_CLOSE = new CloseTagToken(TokenHTML_H5_CLOSE, "h5", "</h5>");
+  final static AbstractTag HTML_H5_OPEN = new OpenTagToken(TokenHTML_H5_OPEN, "h5", "<h5>");
+  final static AbstractTag HTML_H6_CLOSE = new CloseTagToken(TokenHTML_H6_CLOSE, "h6", "</h6>");
+  final static AbstractTag HTML_H6_OPEN = new OpenTagToken(TokenHTML_H6_OPEN, "h6", "<h6>");
+  final static AbstractTag HTML_ITALIC_CLOSE = new CloseTagToken(TokenHTML_ITALIC_CLOSE, "i", "</i>");
+  final static AbstractTag HTML_ITALIC_OPEN = new OpenTagToken(TokenHTML_ITALIC_OPEN, "i", "<i>");
+  final static AbstractTag HTML_BOLD_CLOSE = new CloseTagToken(TokenHTML_BOLD_CLOSE, "b", "</b>");
+  final static AbstractTag HTML_BOLD_OPEN = new OpenTagToken(TokenHTML_BOLD_OPEN, "b", "<b>");
+
+  //
+  final static AbstractTag HTML_PARAGRAPH_CLOSE = new CloseTagToken(TokenHTML_PARAGRAPH_CLOSE, "p", "</p>");
+  final static AbstractTag HTML_PARAGRAPH_OPEN = new OpenTagToken(TokenHTML_PARAGRAPH_OPEN, "p", "<p>");
+  final static AbstractTag HTML_PRE_CLOSE = new CloseTagToken(TokenHTML_PRE_CLOSE, "pre", "</pre>");
+  final static AbstractTag HTML_PRE_OPEN = new OpenTagToken(TokenHTML_PRE_OPEN, "pre", "<pre>");
+  final static AbstractTag HTML_BLOCKQUOTE_CLOSE = new CloseTagToken(TokenHTML_BLOCKQUOTE_CLOSE, "blockquote", "</blockquote>");
+  final static AbstractTag HTML_BLOCKQUOTE_OPEN = new OpenTagToken(TokenHTML_BLOCKQUOTE_OPEN, "blockquote", "<blockquote>");
+  final static AbstractTag HTML_STRIKE_CLOSE = new CloseTagToken(TokenHTML_STRIKE_CLOSE, "strike", "</strike>");
+  final static AbstractTag HTML_STRIKE_OPEN = new OpenTagToken(TokenHTML_STRIKE_OPEN, "strike", "<strike>");
+  final static AbstractTag HTML_STRONG_CLOSE = new CloseTagToken(TokenHTML_STRONG_CLOSE, "strong", "</b>");
+  final static AbstractTag HTML_STRONG_OPEN = new OpenTagToken(TokenHTML_STRONG_OPEN, "strong", "<b>");
+  final static AbstractTag HTML_UNDERLINE_CLOSE = new CloseTagToken(TokenHTML_UNDERLINE_CLOSE, "u", "</u>");
+  final static AbstractTag HTML_UNDERLINE_OPEN = new OpenTagToken(TokenHTML_UNDERLINE_OPEN, "u", "<u>");
+  final static AbstractTag HTML_SUB_CLOSE = new CloseTagToken(TokenHTML_SUB_CLOSE, "sub", "</sub>");
+  final static AbstractTag HTML_SUB_OPEN = new OpenTagToken(TokenHTML_SUB_OPEN, "sub", "<sub>");
+  final static AbstractTag HTML_SUP_CLOSE = new CloseTagToken(TokenHTML_SUP_CLOSE, "sup", "</sup>");
+  final static AbstractTag HTML_SUP_OPEN = new OpenTagToken(TokenHTML_SUP_OPEN, "sup", "<sup>");
+  
+  final static AbstractTag HTML_CENTER_OPEN = new OpenTagToken(TokenHTML_CENTER_OPEN, "center", "<center>");
+  final static AbstractTag HTML_CENTER_CLOSE = new CloseTagToken(TokenHTML_CENTER_CLOSE, "center", "</center>");
+  final static AbstractTag HTML_TT_OPEN = new OpenTagToken(TokenHTML_TT_OPEN, "tt", "<tt>");
+  final static AbstractTag HTML_TT_CLOSE = new CloseTagToken(TokenHTML_TT_CLOSE, "tt", "</tt>");
+  
+  final static AbstractTag HTML_MATH_OPEN = new OpenTagToken(TokenHTML_MATH_OPEN, "math", "<math>");
+  final static AbstractTag HTML_MATH_CLOSE = new CloseTagToken(TokenHTML_MATH_CLOSE, "math", "</math>");
+
+  final static AbstractTag HTML_TABLE_OPEN = new TableTag(TokenHTML_TABLE_OPEN, "table", "<table>");
+  final static AbstractTag HTML_TABLE_CLOSE = new CloseTagToken(TokenHTML_TABLE_CLOSE, "table", "</table>");
+  final static AbstractTag HTML_CAPTION_OPEN = new OpenTagToken(TokenHTML_CAPTION_OPEN, "caption", "<caption>");
+  final static AbstractTag HTML_CAPTION_CLOSE = new CloseTagToken(TokenHTML_CAPTION_CLOSE, "caption", "</caption>");
+  final static AbstractTag HTML_TH_OPEN = new OpenTagToken(TokenHTML_TH_OPEN, "th", "<th>");
+  final static AbstractTag HTML_TH_CLOSE = new CloseTagToken(TokenHTML_TH_CLOSE, "th", "</th>");
+  final static AbstractTag HTML_TR_OPEN = new OpenTagToken(TokenHTML_TR_OPEN, "tr", "<tr>");
+  final static AbstractTag HTML_TR_CLOSE = new CloseTagToken(TokenHTML_TR_CLOSE, "tr", "</tr>");
+  final static AbstractTag HTML_TD_OPEN = new OpenTagToken(TokenHTML_TD_OPEN, "td", "<td>");
+  final static AbstractTag HTML_TD_CLOSE = new CloseTagToken(TokenHTML_TD_CLOSE, "td", "</td>");
+  final static AbstractTag HTML_FONT_OPEN = new FontTag(TokenHTML_FONT_OPEN, "font", "<font>");
+  final static AbstractTag HTML_FONT_CLOSE = new CloseTagToken(TokenHTML_FONT_CLOSE, "font", "</font>");
+  final static AbstractTag HTML_DIV_OPEN = new DivTag(TokenHTML_DIV_OPEN, "div", "<div>");
+  final static AbstractTag HTML_DIV_CLOSE = new CloseTagToken(TokenHTML_DIV_CLOSE, "div", "</div>");
+  
+  final static AbstractTag LIST_OL_START = new AbstractTag(TokenLIST_OL_START);
+  final static AbstractTag LIST_UL_START = new AbstractTag(TokenLIST_UL_START);
+
+  final static AbstractTag HTML_VAR_OPEN = new OpenTagToken(TokenHTML_VAR_OPEN, "var", "<var>");
+  final static AbstractTag HTML_VAR_CLOSE = new CloseTagToken(TokenHTML_VAR_CLOSE, "var", "</var>");
+  final static AbstractTag HTML_CODE_OPEN = new OpenTagToken(TokenHTML_CODE_OPEN, "code", "<code>");
+  final static AbstractTag HTML_CODE_CLOSE = new CloseTagToken(TokenHTML_CODE_CLOSE, "code", "</code>");
+  
+  // strikethrough
+  final static AbstractTag HTML_S_OPEN = new OpenTagToken(TokenHTML_S_OPEN, "s", "<s>");
+  final static AbstractTag HTML_S_CLOSE = new CloseTagToken(TokenHTML_S_CLOSE, "s", "</s>");
+  // small
+  final static AbstractTag HTML_SMALL_OPEN = new OpenTagToken(TokenHTML_SMALL_OPEN, "small", "<small>");
+  final static AbstractTag HTML_SMALL_CLOSE = new CloseTagToken(TokenHTML_SMALL_CLOSE, "small", "</small>");
+
+  final static HashMap OPEN_TAGS = new HashMap();
+  final static HashMap CLOSE_TAGS = new HashMap();
+
+  final static HashSet ENTITY_SET = new HashSet();
+  final static HashMap IMAGE_MAP = new HashMap();
+
+//  private static Log log = LogFactory.getLog(WikipediaFilter.class);
+
+  {
+    for (int i = 0; i < ENTITY_STRINGS.length; i++) {
+      ENTITY_SET.add(ENTITY_STRINGS[i]);
+    }
+    for (int i = 0; i < IMAGE_STRINGS.length; i += 2) {
+      IMAGE_MAP.put(IMAGE_STRINGS[i], IMAGE_STRINGS[i + 1]);
+    }
+    OPEN_TAGS.put("br", HTML_BR_OPEN);
+    OPEN_TAGS.put("hr", HTML_HR_OPEN);
+
+    OPEN_TAGS.put("h1", HTML_H1_OPEN);
+    OPEN_TAGS.put("h2", HTML_H2_OPEN);
+    OPEN_TAGS.put("h3", HTML_H3_OPEN);
+    OPEN_TAGS.put("h4", HTML_H4_OPEN);
+    OPEN_TAGS.put("h5", HTML_H5_OPEN);
+    OPEN_TAGS.put("h6", HTML_H6_OPEN);
+
+    CLOSE_TAGS.put("h1", HTML_H1_CLOSE);
+    CLOSE_TAGS.put("h2", HTML_H2_CLOSE);
+    CLOSE_TAGS.put("h3", HTML_H1_CLOSE);
+    CLOSE_TAGS.put("h4", HTML_H2_CLOSE);
+    CLOSE_TAGS.put("h5", HTML_H1_CLOSE);
+    CLOSE_TAGS.put("h6", HTML_H2_CLOSE);
+
+    OPEN_TAGS.put("em", HTML_EM_OPEN);
+    CLOSE_TAGS.put("em", HTML_EM_CLOSE);
+    OPEN_TAGS.put("i", HTML_ITALIC_OPEN);
+    CLOSE_TAGS.put("i", HTML_ITALIC_CLOSE);
+    OPEN_TAGS.put("b", HTML_BOLD_OPEN);
+    CLOSE_TAGS.put("b", HTML_BOLD_CLOSE);
+    OPEN_TAGS.put("strong", HTML_STRONG_OPEN);
+    CLOSE_TAGS.put("strong", HTML_STRONG_CLOSE);
+    OPEN_TAGS.put("u", HTML_UNDERLINE_OPEN);
+    CLOSE_TAGS.put("u", HTML_UNDERLINE_CLOSE);
+    OPEN_TAGS.put("p", HTML_PARAGRAPH_OPEN);
+    CLOSE_TAGS.put("p", HTML_PARAGRAPH_CLOSE);
+
+    OPEN_TAGS.put("pre", HTML_PRE_OPEN);
+    CLOSE_TAGS.put("pre", HTML_PRE_CLOSE);
+    OPEN_TAGS.put("blockquote", HTML_BLOCKQUOTE_OPEN);
+    CLOSE_TAGS.put("blockquote", HTML_BLOCKQUOTE_CLOSE);
+
+    OPEN_TAGS.put("var", HTML_VAR_OPEN);
+    CLOSE_TAGS.put("var", HTML_VAR_CLOSE);
+    OPEN_TAGS.put("code", HTML_CODE_OPEN);
+    CLOSE_TAGS.put("code", HTML_CODE_CLOSE);
+    OPEN_TAGS.put("s", HTML_S_OPEN);
+    CLOSE_TAGS.put("s", HTML_S_CLOSE);
+    OPEN_TAGS.put("small", HTML_SMALL_OPEN);
+    CLOSE_TAGS.put("small", HTML_SMALL_CLOSE);
+    OPEN_TAGS.put("sub", HTML_SUB_OPEN);
+    CLOSE_TAGS.put("sub", HTML_SUB_CLOSE);
+    OPEN_TAGS.put("sup", HTML_SUP_OPEN);
+    CLOSE_TAGS.put("sup", HTML_SUP_CLOSE);
+    OPEN_TAGS.put("strike", HTML_STRIKE_OPEN);
+    CLOSE_TAGS.put("strike", HTML_STRIKE_CLOSE);
+
+    OPEN_TAGS.put("math", HTML_MATH_OPEN);
+    CLOSE_TAGS.put("math", HTML_MATH_CLOSE);
+    
+    OPEN_TAGS.put("table", HTML_TABLE_OPEN);
+    CLOSE_TAGS.put("table", HTML_TABLE_CLOSE);
+    OPEN_TAGS.put("th", HTML_TH_OPEN);
+    CLOSE_TAGS.put("th", HTML_TH_CLOSE);
+    OPEN_TAGS.put("tr", HTML_TR_OPEN);
+    CLOSE_TAGS.put("tr", HTML_TR_CLOSE);
+    OPEN_TAGS.put("td", HTML_TD_OPEN);
+    CLOSE_TAGS.put("td", HTML_TD_CLOSE);
+    OPEN_TAGS.put("caption", HTML_CAPTION_OPEN);
+    CLOSE_TAGS.put("caption", HTML_CAPTION_CLOSE);
+    
+    OPEN_TAGS.put("font", HTML_FONT_OPEN);
+    CLOSE_TAGS.put("font", HTML_FONT_CLOSE);
+    OPEN_TAGS.put("center", HTML_CENTER_OPEN);
+    CLOSE_TAGS.put("center", HTML_CENTER_CLOSE);
+    OPEN_TAGS.put("tt", HTML_TT_OPEN);
+    CLOSE_TAGS.put("tt", HTML_TT_CLOSE);
+    OPEN_TAGS.put("div", HTML_DIV_OPEN);
+    CLOSE_TAGS.put("div", HTML_DIV_CLOSE);
+  }
+
+  /**
+   * Limits the recursive call of this filter to a depth of RECURSION_LIMIT
+   */
+  final static int RECURSION_LIMIT = 5;
+
+  final static AbstractTag START = new AbstractTag(TokenSTART);
+
+  final static AbstractTag STRIKETHROUGH = new AbstractTag(TokenSTRIKETHROUGH);
+
+  /**
+   * Determines if the specified character may be part of a url
+   */
+  public final static boolean isUrlIdentifierPart(char ch) {
+    if (Character.isLetterOrDigit(ch)) {
+      return true;
+    }
+    final String test = "-_.!~*';/?:@#&=+$,";
+    return test.indexOf(ch) != (-1);
+  }
+
+  /**
+   * Determines if the specified character may be part of a wiki plugin identifier as other than the first character
+   */
+  public final static boolean isWikiPluginIdentifierPart(char ch) {
+    return Character.isLetterOrDigit(ch) || (ch == '_');
+  }
+
+  /**
+   * Determines if the specified character may be part the first character of a wiki plugin identifier
+   */
+  public final static boolean isWikiPluginIdentifierStart(char ch) {
+    return Character.isLetter(ch);
+  }
+
+  public static boolean createStaticImage(String imageTag, StringBuffer buff) {
+    String value = (String) IMAGE_MAP.get(imageTag);
+    if (value != null) {
+      buff.append(MessageFormat.format(value, ARGUMENTS));
+      return true;
+    }
+    return false;
+  }
+
+  //  private MacroRepository macros;
+  
+  public WikipediaFilter() {
+    super();
+  }
+
+  public String filter(String input, FilterContext context) {
+    return filter(input, context, MacroRepository.getInstance(), 0);
+  }
+
+  public String filter(
+    String input,
+    FilterContext context,
+    MacroRepository macros,
+    int recursionLevel) {
+    try {
+      if (++recursionLevel > RECURSION_LIMIT) {
+        String error = "<span class=\"error\">Error - recursion limit exceeded.</span>";
+        return error;
+      }
+
+      StringBuffer result = new StringBuffer(input.length() + input.length() / 10);
+      if (input.startsWith("#html")) {
+        // ignore first line
+        int index = input.indexOf('\n');
+        if (index != (-1)) {
+         
+//          Configuration fUser = Application.get().getUser();
+//          if (fUser.isAdmin()) {
+            // admins are allowed to insert full html directly 
+            String subst = input.substring(index + 1);
+            // for page preview:
+            return subst;
+//          }
+        }
+      }
+      // instantiate inner Parser class
+      WikipediaParser parser = new WikipediaParser(macros, input, result, context, recursionLevel);
+      parser.parse();
+      return result.toString();
+      // Util.substitute(matcher, p, new Perl5Substitution(s, interps), result, limit);
+    } catch (Exception e) {
+      //log.warn("<span class=\"error\">Exception</span>: " + this + ": " + e);
+//      log.warn("Exception for: " + " " + e);
+      e.printStackTrace();
+    } catch (Error err) {
+      //log.warn("<span class=\"error\">Error</span>: " + this + ": " + err);
+//      log.warn("Error for: ");
+      err.printStackTrace();
+    }
+    String error = "<span class=\"error\">Error in Parser.</span>";
+    return error;
+  }
+
+  public static String filterParser(
+    String input,
+    FilterContext context,
+    MacroRepository macros,
+    int recursionLevel) {
+    try {
+      if (++recursionLevel > RECURSION_LIMIT) {
+        return "<span class=\"error\">Error - recursion limit exceeded.</span>";
+      }
+
+      StringBuffer result = new StringBuffer(input.length() + input.length() / 10);
+      // instantiate inner Parser class
+      WikipediaParser parser = new WikipediaParser(macros, input, result, context, recursionLevel);
+      parser.parse();
+      return result.toString();
+      // Util.substitute(matcher, p, new Perl5Substitution(s, interps), result, limit);
+    } catch (Exception e) {
+      //log.warn("<span class=\"error\">Exception</span>: " + this + ": " + e);
+//      log.warn("Exception for: " + " " + e);
+      e.printStackTrace();
+    } catch (Error err) {
+      //log.warn("<span class=\"error\">Error</span>: " + this + ": " + err);
+//      log.warn("Error for: ");
+      err.printStackTrace();
+    }
+
+    return "<span class=\"error\">Error in Parser.</span>";
+  }
+
+  //  private void filterParams(StringBuffer buffer, String name) {
+  //    Map param = fContext.getRenderContext().getParameters();
+  //    if (param != null) {
+  //      if (param.containsKey(name)) {
+  //        Object value = param.get(name);
+  //        if (value instanceof String[]) {
+  //          buffer.append(((String[]) value)[0]);
+  //        } else {
+  //          buffer.append(value);
+  //        }
+  //      } else {
+  //        buffer.append("<");
+  //        buffer.append(name);
+  //        buffer.append(">");
+  //      }
+  //    } else {
+  //      buffer.append("<");
+  //      buffer.append(name);
+  //      buffer.append(">");
+  //    }
+  //  }
+
+  //  public String parseParameters(String unsplittedMacroParameters) {
+  //    int currPos = 0;
+  //    int currEndPos = 0;
+  //    int len = unsplittedMacroParameters.length();
+  //    StringBuffer buffer = new StringBuffer(len);
+  //    char ch;
+  //    while (currPos < len) {
+  //      ch = unsplittedMacroParameters.charAt(currPos++);
+  //      if (ch != '$') {
+  //        buffer.append(ch);
+  //      } else {
+  //        if ((currEndPos = unsplittedMacroParameters.indexOf('|', currPos)) >= 1) {
+  //          filterParams(buffer, unsplittedMacroParameters.substring(currPos, currEndPos));
+  //          currPos = currEndPos + 1;
+  //          buffer.append('|');
+  //        } else {
+  //          if (currPos < len) {
+  //            filterParams(buffer, unsplittedMacroParameters.substring(currPos, len));
+  //          }
+  //        }
+  //      }
+  //    }
+  //    return buffer.toString();
+  //  }
+
+  //  protected Repository getMacroRepository() {
+  //    return macros;
+  //  }
+
+  //  public void setInitialContext(InitialRenderContext context) {
+  //    macros = MacroRepository.getInstance();
+  //    macros.setInitialContext(context);
+  //  }
+
+  public static void copyWhite(StringBuffer result, String text) {
+    final int len = text.length();
+    int currentIndex = 0;
+    int lastIndex = currentIndex;
+    while (currentIndex < len) {
+      switch (text.charAt(currentIndex++)) {
+        case '<' : // special html escape character
+          if (lastIndex < (currentIndex - 1)) {
+            result.append(text.substring(lastIndex, currentIndex - 1));
+            lastIndex = currentIndex;
+          } else {
+            lastIndex++;
+          }
+          result.append("&#60;");
+          break;
+        case '>' : // special html escape character
+          if (lastIndex < (currentIndex - 1)) {
+            result.append(text.substring(lastIndex, currentIndex - 1));
+            lastIndex = currentIndex;
+          } else {
+            lastIndex++;
+          }
+          result.append("&#62;");
+          break;
+        case '&' : // special html escape character
+          if (lastIndex < (currentIndex - 1)) {
+            result.append(text.substring(lastIndex, currentIndex - 1));
+            lastIndex = currentIndex;
+          } else {
+            lastIndex++;
+          }
+          result.append("&#38;");
+          break;
+        case '\'' : // special html escape character
+          if (lastIndex < (currentIndex - 1)) {
+            result.append(text.substring(lastIndex, currentIndex - 1));
+            lastIndex = currentIndex;
+          } else {
+            lastIndex++;
+          }
+          result.append("&#39;");
+          break;
+        case '\"' : // special html escape character
+          if (lastIndex < (currentIndex - 1)) {
+            result.append(text.substring(lastIndex, currentIndex - 1));
+            lastIndex = currentIndex;
+          } else {
+            lastIndex++;
+          }
+          result.append("&#34;");
+          break;
+      }
+    }
+    if (lastIndex < (currentIndex)) {
+      result.append(text.substring(lastIndex, currentIndex));
+    }
+  }
+
+  public static void createMacro(StringBuffer result, String macroCommand, FilterContext context, MacroRepository macros) {
+    String command = "";
+    String endTag;
+
+    String parameterString = null;
+    String macroBodyString = "";
+    int index0 = 0;
+    int index1 = macroCommand.indexOf('}');
+    if ((index0 = macroCommand.indexOf(':')) >= 0 && (index0 < index1)) {
+      command = macroCommand.substring(1, index0);
+      parameterString = macroCommand.substring(index0 + 1, index1);
+    } else {
+      command = macroCommand.substring(1, index1);
+    }
+    Macro macro = (Macro) macros.get(command);
+
+    String completeMacroSubString;
+
+    if ((macro != null) && (macro instanceof IBodyTagSupportMacro)) {
+      endTag = '{' + command + '}';
+      index0 = macroCommand.indexOf(endTag, command.length());
+
+      if (index0 >= 0) {
+        macroBodyString = macroCommand.substring(index1 + 1, index0);
+      }
+    }
+    completeMacroSubString = macroCommand;
+
+    handleMacro(result, completeMacroSubString, command, parameterString, macroBodyString, context, macros);
+
+  }
+
+  private static void handleMacro(
+    StringBuffer result,
+    String completeMacroSubString,
+    String command,
+    String unsplittedMacroParameters,
+    String group3,
+    FilterContext context,
+    MacroRepository macros) {
+    if (command != null) {
+      // {$peng} are variables not macros.
+      if (!command.startsWith("$")) {
+        MacroParameter mParams = context.getMacroParameter();
+
+        if (group3 != null) {
+          mParams.setContent(group3);
+          mParams.setContentStart(0);
+          mParams.setContentEnd(group3.length());
+        }
+        if (unsplittedMacroParameters != null && unsplittedMacroParameters.length() > 1) {
+          //            mParams.setParams(parseParameters(unsplittedMacroParameters));
+          mParams.setParams(unsplittedMacroParameters);
+        }
+        mParams.setStart(0);
+        mParams.setEnd(completeMacroSubString.length());
+
+        // @DANGER: recursive calls may replace macros in included source code
+        try {
+          if (macros.containsKey(command)) {
+
+            Macro macro = (Macro) macros.get(command);
+            // recursively filter macros within macros
+            if (null != mParams.getContent() && !(macro instanceof INoParserBodyFilterMacro)) {
+              mParams.setContent(filterParser(mParams.getContent(), context, macros, 0));
+            }
+            StringBufferWriter writer = new StringBufferWriter(new StringBuffer(256));
+            macro.execute(writer, mParams);
+            StringBuffer buffer = writer.getBuffer();
+            if (macro instanceof IRenderResultMacro) {
+              result.append(filterParser(buffer.toString(), context, macros, 0));
+            } else {
+              result.append(buffer);
+            }
+
+          } else if (command.startsWith("!")) {
+            RenderEngine engine = context.getRenderContext().getRenderEngine();
+            if (engine instanceof IncludeRenderEngine) {
+              String include = ((IncludeRenderEngine) engine).include(command.substring(1));
+              if (null != include) {
+                // Filter paramFilter = new ParamFilter(mParams);
+                // included = paramFilter.filter(included, null);
+                //                  fResult.append(include);
+                result.append(filterParser(include, context, macros, 0));
+              } else {
+                result.append(command.substring(1) + " not found.");
+              }
+            }
+            return;
+          } else {
+            //              fResult.append(group0);
+            copyWhite(result, completeMacroSubString);
+            return;
+          }
+        } catch (IllegalArgumentException e) {
+          result.append("<div class=\"error\">" + command + ": " + e.getMessage() + "</div>");
+
+          e.printStackTrace();
+
+        } catch (Throwable e) {
+//          log.warn("MacroFilter: unable to format macro: " + command, e);
+          result.append("<div class=\"error\">" + command + ": " + e.getMessage() + "</div>");
+          e.printStackTrace();
+          return;
+        }
+      } else {
+        result.append("<");
+        result.append(command.substring(1));
+        result.append(">");
+      }
+    } else {
+      //        fResult.append(group0);
+      copyWhite(result, completeMacroSubString);
+    }
+  }
+
+  public static void createExternalLink(StringBuffer result, RenderEngine wikiEngine, String urlString) {
+
+    // Does our engine know images?
+    if (wikiEngine instanceof ImageRenderEngine) {
+      result.append(((ImageRenderEngine) wikiEngine).getExternalImageLink());
+    }
+    result.append("<span class=\"nobr\">");
+    result.append("<a href=\"");
+    result.append(Encoder.escape(urlString));
+    result.append("\">");
+    result.append(Encoder.toEntity(urlString.charAt(0)) + urlString.substring(1));
+    result.append("</a></span>");
+  }
+
+  public static void handleSnipLink(StringBuffer result, RenderEngine wikiEngine, String name) {
+    if (name != null) {
+      int index = name.indexOf("http://");
+      // Configuration probably wrote [http://radeox.org] instead of http://radeox.org
+      if (index != -1) {
+        createExternalLink(result, wikiEngine, name.substring(index));
+        // show error
+        // fResult.append("<div class=\"error\">Do not surround URLs with [...].</div>");
+      } else {
+        // trim the name and unescape it
+        name = Encoder.unescape(name.trim());
+        //                Is there an alias like [alias|link] ?
+        int pipeIndex = name.indexOf('|');
+        String alias = "";
+        if (-1 != pipeIndex) {
+          alias = name.substring(0, pipeIndex);
+          name = name.substring(pipeIndex + 1);
+        }
+
+        int hashIndex = name.lastIndexOf('#');
+
+        String hash = "";
+        if (-1 != hashIndex && hashIndex != name.length() - 1) {
+          hash = name.substring(hashIndex + 1);
+          name = name.substring(0, hashIndex);
+        }
+
+        int colonIndex = name.indexOf(':');
+        // typed link ?
+        if (-1 != colonIndex) {
+          // for now throw away the fType information
+          name = name.substring(colonIndex + 1);
+        }
+
+        int atIndex = name.lastIndexOf('@');
+        // InterWiki link ?
+        if (-1 != atIndex) {
+          String extSpace = name.substring(atIndex + 1);
+          // known extarnal space ?
+          InterWiki interWiki = InterWiki.getInstance();
+          if (interWiki.contains(extSpace)) {
+            name = name.substring(0, atIndex);
+            Writer writer = new StringBufferWriter(result);
+            try {
+              if (-1 != hashIndex) {
+                interWiki.expand(writer, extSpace, name, hash);
+              } else {
+                interWiki.expand(writer, extSpace, name, "");
+              }
+            } catch (IOException e) {
+//              log.debug("InterWiki " + extSpace + " not found.");
+            }
+          } else {
+            result.append("&#91;<span class=\"error\">");
+            result.append(name);
+            result.append("?</span>&#93;");
+          }
+        } else {
+          // internal link
+          if (wikiEngine != null && wikiEngine instanceof WikiRenderEngine) {
+            if (((WikiRenderEngine) wikiEngine).exists(name)) {
+              String view = name;
+              if (-1 != pipeIndex) {
+                view = alias;
+              }
+              // Do not add hash if an alias was given
+              if (-1 != hashIndex) {
+                ((WikiRenderEngine) wikiEngine).appendLink(result, name, view, hash);
+              } else {
+                ((WikiRenderEngine) wikiEngine).appendLink(result, name, view);
+              }
+            } else if (((WikiRenderEngine) wikiEngine).showCreate()) {
+              ((WikiRenderEngine) wikiEngine).appendCreateLink(result, name, name);
+              // links with "create" are not cacheable because
+              // a missing wiki could be created
+              // TODO is this ok?
+              //  fContext.getRenderContext().setCacheable(false);
+            } else {
+              // cannot display/create wiki, so just display the text
+              result.append(name);
+            }
+          } else {
+            // cannot display/create wiki, so just display the text
+            result.append(name);
+          }
+        }
+      }
+    }
+  }
+
+  public static void handleWikipediaLink(StringBuffer result, RenderEngine wikiEngine, String name, String suffix) {
+    if (name != null) {
+      int index = name.indexOf("http://");
+      // Configuration probably wrote [http://radeox.org] instead of http://radeox.org
+      if (index != -1) {
+        // createExternalLink(result, wikiEngine, name.substring(index));
+        String urlString = name.substring(index);
+        // Wikipedia like style:
+        int pipeIndex = urlString.indexOf(' ');
+        String alias = "";
+        if (-1 != pipeIndex) {
+          alias = urlString.substring(pipeIndex + 1);
+          urlString = urlString.substring(0, pipeIndex);
+        } else {
+          alias = urlString;
+        }
+
+        if (wikiEngine instanceof ImageRenderEngine) {
+          result.append(((ImageRenderEngine) wikiEngine).getExternalImageLink());
+        }
+        result.append("<span class=\"nobr\">");
+        result.append("<a href=\"");
+        result.append(Encoder.escape(urlString));
+        result.append("\">");
+        result.append(Encoder.toEntity(alias.charAt(0)) + alias.substring(1));
+        result.append("</a></span>");
+      } else {
+        if (suffix == null) {
+          suffix = "";
+        }
+        // trim the name and unescape it
+        name = Encoder.unescape(name.trim());
+        
+        name = name.replaceAll(":","/");
+        
+        //                Is there an alias like [alias|link] ?
+        int pipeIndex = name.indexOf('|');
+        String alias = "";
+        if (-1 != pipeIndex) {
+          alias = name.substring(pipeIndex + 1);
+          name = name.substring(0, pipeIndex);
+        }
+
+        int hashIndex = name.lastIndexOf('#');
+
+        String hash = "";
+        if (-1 != hashIndex && hashIndex != name.length() - 1) {
+          hash = name.substring(hashIndex + 1);
+          name = name.substring(0, hashIndex);
+        }
+
+        int colonIndex = name.indexOf(':');
+        // typed link ?
+        if (-1 != colonIndex) {
+          // for now throw away the fType information
+          name = name.substring(colonIndex + 1);
+        }
+
+        int atIndex = name.lastIndexOf('@');
+        // InterWiki link ?
+        if (-1 != atIndex) {
+          String extSpace = name.substring(atIndex + 1);
+          // known external space ?
+          InterWiki interWiki = InterWiki.getInstance();
+          if (interWiki.contains(extSpace)) {
+            name = name.substring(0, atIndex);
+            Writer writer = new StringBufferWriter(result);
+            try {
+              if (-1 != hashIndex) {
+                interWiki.expand(writer, extSpace, name, hash);
+              } else {
+                interWiki.expand(writer, extSpace, name, "");
+              }
+            } catch (IOException e) {
+//              log.debug("InterWiki " + extSpace + " not found.");
+            }
+          } else {
+            result.append("&#91;<span class=\"error\">");
+            result.append(name);
+            result.append("?</span>&#93;");
+          }
+        } else {
+          // internal link
+          if (wikiEngine != null && wikiEngine instanceof WikiRenderEngine) {
+            if (((WikiRenderEngine) wikiEngine).exists(name)) {
+              String view = name + suffix;
+              if (-1 != pipeIndex) {
+                view = alias + suffix;
+              }
+              // Do not add hash if an alias was given
+              if (-1 != hashIndex) {
+                ((WikiRenderEngine) wikiEngine).appendLink(result, name, view, hash);
+              } else {
+                ((WikiRenderEngine) wikiEngine).appendLink(result, name, view);
+              }
+            } else if (((WikiRenderEngine) wikiEngine).showCreate()) {
+              ((WikiRenderEngine) wikiEngine).appendCreateLink(result, name, name + suffix);
+              // links with "create" are not cacheable because
+              // a missing wiki could be created
+              // TODO is this ok?
+              //  fContext.getRenderContext().setCacheable(false);
+            } else {
+              // cannot display/create wiki, so just display the text
+              result.append(name);
+            }
+          } else {
+            // cannot display/create wiki, so just display the text
+            result.append(name);
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/archive/org.plog4u.wiki/src/org/plog4u/wiki/filter/WikipediaParser.java b/archive/org.plog4u.wiki/src/org/plog4u/wiki/filter/WikipediaParser.java
new file mode 100644 (file)
index 0000000..5383fb7
--- /dev/null
@@ -0,0 +1,2739 @@
+package org.plog4u.wiki.filter;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.NoSuchElementException;
+import java.util.Stack;
+import java.util.StringTokenizer;
+
+//import org.apache.commons.logging.Log;
+//import org.apache.commons.logging.LogFactory;
+import org.plog4u.wiki.filter.WikipediaFilter.InvalidInputException;
+import org.plog4u.wiki.filter.tags.AbstractTag;
+import org.plog4u.wiki.filter.tags.CloseTagToken;
+import org.plog4u.wiki.filter.tags.ListToken;
+import org.plog4u.wiki.filter.tags.OpenTagToken;
+import org.plog4u.wiki.filter.tags.SpecialTagToken;
+import org.radeox.api.engine.ImageRenderEngine;
+import org.radeox.api.engine.IncludeRenderEngine;
+import org.radeox.api.engine.RenderEngine;
+import org.radeox.api.engine.WikiRenderEngine;
+import org.radeox.filter.context.FilterContext;
+import org.radeox.filter.interwiki.InterWiki;
+import org.radeox.macro.Macro;
+import org.radeox.macro.MacroRepository;
+import org.radeox.macro.parameter.MacroParameter;
+import org.radeox.util.Encoder;
+import org.radeox.util.StringBufferWriter;
+
+/**
+ * A parser for the WikipediaFilter
+ * 
+ * @see org.plog4u.wiki.filter.WikipediaFilter
+ */
+public class WikipediaParser {
+  //  private static Log log = LogFactory.getLog(WikipediaFilter.class);
+
+  MacroRepository fMacros;
+
+  private FilterContext fContext;
+
+  private RenderEngine fWikiEngine;
+
+  // TODO check, if this counter is correct in recursions:
+  private int fImageCounter;
+
+  /**
+   * The current snip
+   */
+  //  private Snip fSnip;
+  /**
+   * If the snip contains headings for a &quot;table of content&quot; this buffer temporarily contains the start of the snip and the
+   * &quot;table of content&quot;
+   */
+  private StringBuffer fResultBufferHeader = null;
+
+  /**
+   * The buffer for the resulting HTML rendering from the current snip.
+   */
+  private StringBuffer fResultBuffer;
+
+  /**
+   * The wiki syntax string which should be parsed
+   */
+  private char[] fSource;
+
+  /**
+   * The corresponding String for the character source array
+   */
+  private final String fStringSource;
+
+  /**
+   * The current scanned character
+   */
+  private char fCurrentCharacter;
+
+  /**
+   * The current offset in the character source array
+   */
+  private int fCurrentPosition;
+
+  /**
+   * The current recursion level for this parser
+   */
+  private int fRecursionLevel;
+
+  private Stack fTokenStack;
+
+  //  private Stack fTableStack;
+
+  private boolean fWhiteStart = false;
+
+  private int fWhiteStartPosition = 0;
+
+  //  private TeXParser fTeXParser;
+  //  private TeXParser fTeXImageParser;
+  /**
+   * 
+   * &quot;table of content&quot;
+   *  
+   */
+  private ArrayList fTableOfContent = null;
+
+  //  private String fSrcPath;
+  //  private String fBinPath;
+
+  public WikipediaParser(MacroRepository macros, String stringSource, StringBuffer result, FilterContext context, int recursionLevel) {
+    fContext = context;
+    fWikiEngine = context.getRenderContext().getRenderEngine();
+
+    //    try {
+    //      SnipMacroParameter params = (SnipMacroParameter)
+    // fContext.getMacroParameter();
+    //      fSnip = params.getSnipRenderContext().getSnip();
+    //    } catch (ClassCastException e) {
+    //      e.printStackTrace();
+    //    }
+    fMacros = macros;
+    fResultBuffer = result;
+    fStringSource = stringSource;
+    setSource(stringSource.toCharArray());
+    fRecursionLevel = recursionLevel;
+    fTokenStack = new Stack();
+    //    fTableStack = new Stack();
+    //    fTeXParser = new TeXParser("", "m:");
+    //    fTeXImageParser = new TeXParser("", "");
+    fImageCounter = 1;
+
+    //    fSrcPath = (String) fContext.getRenderContext().get("srcpath");
+    //    if (fSrcPath==null) {
+    //      fSrcPath = "";
+    //    }
+    //    fBinPath = (String) fContext.getRenderContext().get("binpath");
+    //    if (fBinPath==null) {
+    //      fBinPath = "";
+    //    }
+  }
+
+  /**
+   * Check until a new-line was found, if there are only whitespace characters before the given endposition.
+   * 
+   * @param startPosition
+   * @param endPosition
+   * @return -1 if no whitespace line is found from the end (i.e. endPosition); otherwise the offset directly after where the
+   *         new-line was found
+   */
+  private int checkWhitespaces(int startPosition, int endPosition) {
+    char tempChar;
+    while (endPosition >= startPosition) {
+      if ((tempChar = fSource[endPosition--]) == '\n') {
+        return endPosition + 2;
+      }
+      if (tempChar != ' ' && tempChar != '\t' && tempChar != '\r') {
+        return -1;
+      }
+    }
+    if (endPosition < startPosition && endPosition >= 0) {
+      if ((tempChar = fSource[endPosition]) != '\n') {
+        return -1;
+      }
+    } else if (endPosition == (-1) && startPosition == 0) {
+      // special case at the start of a string
+      return 0;
+    }
+    return startPosition;
+  }
+
+  /**
+   * copy the content in the resulting buffer and escape special html characters (&lt; &gt; &quot; &amp; &#39;)
+   */
+  private void copyWhite(boolean whiteStart, final int whiteStartPosition, final int diff) {
+    if (whiteStart) {
+      final int len = fCurrentPosition - diff;
+      int currentIndex = whiteStartPosition;
+      int lastIndex = currentIndex;
+      while (currentIndex < len) {
+        switch (fSource[currentIndex++]) {
+        case '<': // special html escape character
+          if (lastIndex < (currentIndex - 1)) {
+            fResultBuffer.append(fSource, lastIndex, currentIndex - lastIndex - 1);
+            lastIndex = currentIndex;
+          } else {
+            lastIndex++;
+          }
+          fResultBuffer.append("&#60;");
+          break;
+        case '>': // special html escape character
+          if (lastIndex < (currentIndex - 1)) {
+            fResultBuffer.append(fSource, lastIndex, currentIndex - lastIndex - 1);
+            lastIndex = currentIndex;
+          } else {
+            lastIndex++;
+          }
+          fResultBuffer.append("&#62;");
+          break;
+        case '&': // special html escape character
+          if (lastIndex < (currentIndex - 1)) {
+            fResultBuffer.append(fSource, lastIndex, currentIndex - lastIndex - 1);
+            lastIndex = currentIndex;
+          } else {
+            lastIndex++;
+          }
+          fResultBuffer.append("&#38;");
+          break;
+        case '\'': // special html escape character
+          if (lastIndex < (currentIndex - 1)) {
+            fResultBuffer.append(fSource, lastIndex, currentIndex - lastIndex - 1);
+            lastIndex = currentIndex;
+          } else {
+            lastIndex++;
+          }
+          fResultBuffer.append("&#39;");
+          break;
+        case '\"': // special html escape character
+          if (lastIndex < (currentIndex - 1)) {
+            fResultBuffer.append(fSource, lastIndex, currentIndex - lastIndex - 1);
+            lastIndex = currentIndex;
+          } else {
+            lastIndex++;
+          }
+          fResultBuffer.append("&#34;");
+          break;
+        }
+      }
+      if (lastIndex < (currentIndex)) {
+        fResultBuffer.append(fSource, lastIndex, currentIndex - lastIndex);
+      }
+      fWhiteStart = false;
+    }
+  }
+
+  /**
+   * copy the text in the resulting buffer and escape special html characters (&lt; &gt; &quot; &amp; &#39;)
+   */
+  private void copyWhite(String text) {
+    final int len = text.length();
+    int currentIndex = 0;
+    int lastIndex = currentIndex;
+    while (currentIndex < len) {
+      switch (text.charAt(currentIndex++)) {
+      case '<': // special html escape character
+        if (lastIndex < (currentIndex - 1)) {
+          fResultBuffer.append(text.substring(lastIndex, currentIndex - 1));
+          lastIndex = currentIndex;
+        }
+        fResultBuffer.append("&#60;");
+        break;
+      case '>': // special html escape character
+        if (lastIndex < (currentIndex - 1)) {
+          fResultBuffer.append(text.substring(lastIndex, currentIndex - 1));
+          lastIndex = currentIndex;
+        } else {
+          lastIndex++;
+        }
+        fResultBuffer.append("&#62;");
+        break;
+      case '&': // special html escape character
+        if (lastIndex < (currentIndex - 1)) {
+          fResultBuffer.append(text.substring(lastIndex, currentIndex - 1));
+          lastIndex = currentIndex;
+        } else {
+          lastIndex++;
+        }
+        fResultBuffer.append("&#38;");
+        break;
+      case '\'': // special html escape character
+        if (lastIndex < (currentIndex - 1)) {
+          fResultBuffer.append(text.substring(lastIndex, currentIndex - 1));
+          lastIndex = currentIndex;
+        } else {
+          lastIndex++;
+        }
+        fResultBuffer.append("&#39;");
+        break;
+      case '\"': // special html escape character
+        if (lastIndex < (currentIndex - 1)) {
+          fResultBuffer.append(text.substring(lastIndex, currentIndex - 1));
+          lastIndex = currentIndex;
+        } else {
+          lastIndex++;
+        }
+        fResultBuffer.append("&#34;");
+        break;
+      }
+    }
+    if (lastIndex < (currentIndex)) {
+      fResultBuffer.append(text.substring(lastIndex, currentIndex));
+    }
+  }
+
+  /**
+   * Copy the text in the resulting buffer and escape special html characters (&lt; &gt; &quot; &amp; &#39;) Additionally every
+   * newline will be replaced by &lt;br/&gt;
+   */
+  private void copyNowikiNewLine(String text) {
+    final int len = text.length();
+    int currentIndex = 0;
+    int lastIndex = currentIndex;
+    while (currentIndex < len) {
+      switch (text.charAt(currentIndex++)) {
+      case '\n':
+        if (lastIndex < (currentIndex - 1)) {
+          fResultBuffer.append(text.substring(lastIndex, currentIndex - 1));
+          lastIndex = currentIndex;
+        } else {
+          lastIndex++;
+        }
+        fResultBuffer.append("<br/>");
+        break;
+      case '<': // special html escape character
+        if (lastIndex < (currentIndex - 1)) {
+          fResultBuffer.append(text.substring(lastIndex, currentIndex - 1));
+          lastIndex = currentIndex;
+        } else {
+          lastIndex++;
+        }
+        fResultBuffer.append("&#60;");
+        break;
+      case '>': // special html escape character
+        if (lastIndex < (currentIndex - 1)) {
+          fResultBuffer.append(text.substring(lastIndex, currentIndex - 1));
+          lastIndex = currentIndex;
+        } else {
+          lastIndex++;
+        }
+        fResultBuffer.append("&#62;");
+        break;
+      //      case '&': // special html escape character
+      //        if (lastIndex < (currentIndex - 1)) {
+      //          fResultBuffer.append(text.substring(lastIndex, currentIndex - 1));
+      //          lastIndex = currentIndex;
+      //        } else {
+      //          lastIndex++;
+      //        }
+      //        fResultBuffer.append("&#38;");
+      //        break;
+      case '\'': // special html escape character
+        if (lastIndex < (currentIndex - 1)) {
+          fResultBuffer.append(text.substring(lastIndex, currentIndex - 1));
+          lastIndex = currentIndex;
+        } else {
+          lastIndex++;
+        }
+        fResultBuffer.append("&#39;");
+        break;
+      case '\"': // special html escape character
+        if (lastIndex < (currentIndex - 1)) {
+          fResultBuffer.append(text.substring(lastIndex, currentIndex - 1));
+          lastIndex = currentIndex;
+        } else {
+          lastIndex++;
+        }
+        fResultBuffer.append("&#34;");
+        break;
+      }
+    }
+    if (lastIndex < (currentIndex)) {
+      fResultBuffer.append(text.substring(lastIndex, currentIndex));
+    }
+  }
+
+  /**
+   * Render the HTML token which are defined in the OPEN_TAGS and CLOSE_TAGS map
+   * 
+   * @return
+   */
+  public int getHTMLToken() {
+    int currentHtmlPosition = fCurrentPosition;
+    try {
+      char closeCharacter;
+      char nextCharacter;
+      if (getNextChar('/')) {
+        currentHtmlPosition++;
+        // closing tag
+        int r = readUntilCharOrEOL('>');
+        if (r != 1) {
+          return WikipediaFilter.TokenNotFound;
+        }
+        String closeTagString = new String(fSource, currentHtmlPosition, fCurrentPosition - currentHtmlPosition - 1).toLowerCase();
+        //          System.out.println(closeTagString);
+        StringTokenizer tagTokenizer = new StringTokenizer(closeTagString);
+        String tokenString;
+        try {
+          tokenString = tagTokenizer.nextToken();
+          CloseTagToken token = (CloseTagToken) WikipediaFilter.CLOSE_TAGS.get(tokenString);
+          if (token == null) {
+            return WikipediaFilter.TokenNotFound;
+          }
+          Object topToken = fTokenStack.peek();
+          if (topToken instanceof OpenTagToken && ((OpenTagToken) topToken).getTagName() == token.getTagName()) {
+            fTokenStack.pop();
+            //            if (token.getTagName().equals("table")) {
+            //              fTableStack.pop();
+            //            }
+            copyWhite(fWhiteStart, fWhiteStartPosition, 3 + tokenString.length());
+            fWhiteStart = false;
+            fResultBuffer.append(token.getCloseTag());
+            return WikipediaFilter.TokenIgnore;
+          }
+          fWhiteStart = false;
+          unexpectedTag(token.getTagName());
+          return WikipediaFilter.TokenIgnore;
+        } catch (NoSuchElementException e) {
+          return WikipediaFilter.TokenNotFound;
+        }
+
+      } else {
+        // opening tag
+        String tokenString;
+        int tagNameStart = fCurrentPosition;
+        int tokenLength = 0;
+        while (Character.isJavaIdentifierStart(fSource[fCurrentPosition++])) {
+          tokenLength++;
+        }
+        try {
+          tokenString = new String(fSource, tagNameStart, fCurrentPosition - tagNameStart - 1); //tagTokenizer.nextToken();
+          OpenTagToken token = (OpenTagToken) WikipediaFilter.OPEN_TAGS.get(tokenString);
+          if (token == null) {
+            return WikipediaFilter.TokenNotFound;
+          }
+          copyWhite(fWhiteStart, fWhiteStartPosition, (fCurrentPosition - tagNameStart) + 1);
+          fWhiteStart = false;
+
+          if (token instanceof SpecialTagToken) {
+            fResultBuffer.append(token.getOpenTag());
+            while (Character.isWhitespace(fSource[fCurrentPosition])) {
+              fCurrentPosition++;
+            }
+            if (fSource[fCurrentPosition] == '/') {
+              fCurrentPosition++;
+            }
+            if (fSource[fCurrentPosition] == '>') {
+              fCurrentPosition++;
+            }
+          } else if (token instanceof OpenTagToken) {
+            fResultBuffer.append("<");
+            fResultBuffer.append(token.getTagName());
+            fTokenStack.push(token);
+            fCurrentPosition = token.scan(fResultBuffer, fSource, fCurrentPosition - 1);
+            fResultBuffer.append(">");
+          }
+
+          //                                   System.out.println(fResultBuffer);
+          return WikipediaFilter.TokenIgnore;
+        } catch (NoSuchElementException e) {
+          return WikipediaFilter.TokenNotFound;
+        }
+      }
+
+    } catch (IndexOutOfBoundsException e) {
+      //
+    }
+    fCurrentPosition = currentHtmlPosition;
+    return WikipediaFilter.TokenNotFound;
+  }
+
+  public final boolean getNextChar(char testedChar) {
+    int temp = fCurrentPosition;
+    try {
+      fCurrentCharacter = fSource[fCurrentPosition++];
+      if (fCurrentCharacter != testedChar) {
+        fCurrentPosition = temp;
+        return false;
+      }
+      return true;
+
+    } catch (IndexOutOfBoundsException e) {
+      fCurrentPosition = temp;
+      return false;
+    }
+  }
+
+  public final int getNextChar(char testedChar1, char testedChar2) {
+    int temp = fCurrentPosition;
+    try {
+      int result;
+      fCurrentCharacter = fSource[fCurrentPosition++];
+      if (fCurrentCharacter == testedChar1)
+        result = 0;
+      else if (fCurrentCharacter == testedChar2)
+        result = 1;
+      else {
+        fCurrentPosition = temp;
+        return -1;
+      }
+      return result;
+    } catch (IndexOutOfBoundsException e) {
+      fCurrentPosition = temp;
+      return -1;
+    }
+  }
+
+  public final boolean getNextCharAsDigit() {
+    int temp = fCurrentPosition;
+    try {
+      fCurrentCharacter = fSource[fCurrentPosition++];
+      if (!Character.isDigit(fCurrentCharacter)) {
+        fCurrentPosition = temp;
+        return false;
+      }
+      return true;
+    } catch (IndexOutOfBoundsException e) {
+      fCurrentPosition = temp;
+      return false;
+    }
+  }
+
+  public final boolean getNextCharAsDigit(int radix) {
+
+    int temp = fCurrentPosition;
+    try {
+      fCurrentCharacter = fSource[fCurrentPosition++];
+
+      if (Character.digit(fCurrentCharacter, radix) == -1) {
+        fCurrentPosition = temp;
+        return false;
+      }
+      return true;
+    } catch (IndexOutOfBoundsException e) {
+      fCurrentPosition = temp;
+      return false;
+    }
+  }
+
+  public final int getNumberOfChar(char testedChar) {
+    int number = 0;
+    try {
+      while ((fCurrentCharacter = fSource[fCurrentPosition++]) == testedChar) {
+        number++;
+      }
+    } catch (IndexOutOfBoundsException e) {
+
+    }
+    fCurrentPosition--;
+    return number;
+  }
+
+  public final char[] getListChars() {
+
+    int startPosition = fCurrentPosition - 1;
+    try {
+      while (true) {
+        fCurrentCharacter = fSource[fCurrentPosition++];
+        if (fCurrentCharacter != '*' && fCurrentCharacter != '#') {
+          break;
+        }
+      }
+    } catch (IndexOutOfBoundsException e) {
+      //
+    }
+    fCurrentPosition--;
+    char[] result = new char[fCurrentPosition - startPosition];
+    System.arraycopy(fSource, startPosition, result, 0, fCurrentPosition - startPosition);
+    return result;
+  }
+
+  public boolean getNextCharAsWikiPluginIdentifierPart() {
+    int temp = fCurrentPosition;
+    try {
+      fCurrentCharacter = fSource[fCurrentPosition++];
+
+      if (!WikipediaFilter.isWikiPluginIdentifierPart(fCurrentCharacter)) {
+        fCurrentPosition = temp;
+        return false;
+      }
+      return true;
+    } catch (IndexOutOfBoundsException e) {
+      fCurrentPosition = temp;
+      return false;
+    }
+  }
+
+  private void stopList() {
+    while (!fTokenStack.isEmpty()) {
+      AbstractTag tok = (AbstractTag) fTokenStack.peek();
+      if (tok.equals(WikipediaFilter.LIST_UL_START)) {
+        fTokenStack.pop();
+        fResultBuffer.append("</li></ul>");
+      } else if (tok.equals(WikipediaFilter.LIST_OL_START)) {
+        fTokenStack.pop();
+        fResultBuffer.append("</li></ol>");
+      } else if (tok == WikipediaFilter.BOLD) {
+        fTokenStack.pop();
+        fResultBuffer.append("</b>");
+      } else if (tok == WikipediaFilter.ITALIC) {
+        fTokenStack.pop();
+        fResultBuffer.append("</i>");
+      } else if (tok == WikipediaFilter.STRONG) {
+        fTokenStack.pop();
+        fResultBuffer.append("</strong>");
+      } else if (tok == WikipediaFilter.EM) {
+        fTokenStack.pop();
+        fResultBuffer.append("</em>");
+      } else if (tok == WikipediaFilter.STRIKETHROUGH) {
+        fTokenStack.pop();
+        fResultBuffer.append("</strike>");
+      } else {
+        break;
+      }
+    }
+  }
+
+  protected int getNextToken() throws InvalidInputException {
+    boolean startOfIndent = false;
+    fWhiteStartPosition = 0;
+    fWhiteStart = false;
+    try {
+      while (true) {
+        //          fStartPosition = fCurrentPosition;
+        fCurrentCharacter = fSource[fCurrentPosition++];
+
+        // ---------Identify the next token-------------
+        switch (fCurrentCharacter) {
+        case '\n':
+          if (fWhiteStart) {
+            int tempPosition = checkWhitespaces(fWhiteStartPosition, fCurrentPosition - 2);
+            if (tempPosition >= 0) {
+              copyWhite(fWhiteStart, fWhiteStartPosition, fCurrentPosition - (++tempPosition));
+              fWhiteStart = false;
+              stopList();
+              fResultBuffer.append("<p/>");
+              //                                                       continue;
+            }
+
+          }
+          int fStartPrePosition = fCurrentPosition;
+          boolean preSection = false;
+          try {
+            while (fSource[fCurrentPosition++] == ' ') {
+              fCurrentCharacter = fSource[fCurrentPosition++];
+              while (fCurrentCharacter != '\n') {
+                if (!Character.isWhitespace(fCurrentCharacter)) {
+                  //                                                                    preformatted section starts here
+                  preSection = true;
+                }
+                fCurrentCharacter = fSource[fCurrentPosition++];
+              }
+            }
+            --fCurrentPosition;
+          } catch (IndexOutOfBoundsException e) {
+
+          }
+          if (preSection && fRecursionLevel == 1) {
+            String preString;
+            copyWhite(fWhiteStart, fStartPrePosition, fCurrentPosition - fStartPrePosition);
+            fWhiteStart = true;
+            fResultBuffer.append("<pre>");
+            //            copyWhite(fWhiteStart, fStartPrePosition, 1);
+            preString = new String(fSource, fStartPrePosition, fCurrentPosition - fStartPrePosition - 1) + '\n';
+            fResultBuffer.append(WikipediaFilter.filterParser(preString, fContext, fMacros, fRecursionLevel));
+            //            preString = new String(fSource, fStartPrePosition, fCurrentPosition - fStartPrePosition - 1)+'\n';
+            //            int preIndex = 0;
+            //            int lastIndex = 0;
+            //            while (preIndex>=0) {
+            //              preIndex = preString.indexOf('\n', lastIndex);
+            //              if (preIndex>=0) {
+            //                fResultBuffer.append(WikipediaFilter.filterParser(preString.substring(lastIndex,preIndex), fContext,
+            // fCachedPage, fMacros, fRecursionLevel));
+            //                fResultBuffer.append('\n');
+            //                lastIndex = ++preIndex;
+            //              }
+            //            }
+            fResultBuffer.append("</pre>");
+            fWhiteStart = false;
+            continue;
+          } else {
+            fCurrentPosition = fStartPrePosition;
+          }
+          break;
+        case ':':
+          if (isStartOfLine()) {
+            copyWhite(fWhiteStart, fWhiteStartPosition, 1);
+            fWhiteStart = false;
+
+            int levelHeader = getNumberOfChar(':') + 1;
+            int startHeadPosition = fCurrentPosition;
+            if (readUntilEOL()) {
+              String head = new String(fSource, startHeadPosition, fCurrentPosition - startHeadPosition);
+              for (int i = 0; i < levelHeader; i++) {
+                fResultBuffer.append("<dl><dd>");
+              }
+              fResultBuffer.append(head);
+              for (int i = 0; i < levelHeader; i++) {
+                fResultBuffer.append("</dd></dl>");
+              }
+              continue;
+            }
+
+            continue;
+          }
+          break;
+        case ';':
+          if (isStartOfLine() && getNextChar(' ')) {
+            copyWhite(fWhiteStart, fWhiteStartPosition, 1);
+            fWhiteStart = false;
+
+            int startHeadPosition = fCurrentPosition;
+            if (readUntilEOL()) {
+              // TODO not correct - improve this
+              String head = new String(fSource, startHeadPosition, fCurrentPosition - startHeadPosition);
+              int index = head.indexOf(": ");
+              if (index > 0) {
+                fResultBuffer.append("<dl><dt>");
+                fResultBuffer.append(head.substring(0,index));
+                fResultBuffer.append("</dt><dd>");
+                fResultBuffer.append(head.substring(index+2));
+                fResultBuffer.append("</dd></dl>");
+              } else {
+                fResultBuffer.append("<dl><dt>");
+                fResultBuffer.append(head);
+                fResultBuffer.append("</dt></dl>");
+              }
+              continue;
+            }
+
+            continue;
+          }
+          break;
+        //                             case '\\': // special characters follow
+        //                                     copyWhite(fWhiteStart, fWhiteStartPosition, 1);
+        //                                     fWhiteStart = false;
+        //                                     try {
+        //                                             fCurrentCharacter = fSource[fCurrentPosition++];
+        //                                             switch (fCurrentCharacter) {
+        //                                             case '\\': // newline
+        //                                                     if ((fCurrentCharacter = fSource[fCurrentPosition++]) == '\\') {
+        //                                                             fResultBuffer.append(Encoder
+        //                                                                             .toEntity(fCurrentCharacter));
+        //                                                             break;
+        //                                                     } else {
+        //                                                             fResultBuffer.append("<br />");
+        //                                                             break;
+        //                                                     }
+        //                                             default:
+        //                                                     fResultBuffer.append(Encoder
+        //                                                                     .toEntity(fCurrentCharacter));
+        //                                             }
+        //                                     } catch (IndexOutOfBoundsException e) {
+        //
+        //                                     }
+        //                                     continue;
+        //          case '$' : // detect tex math
+        //            copyWhite(fWhiteStart, fWhiteStartPosition, 1);
+        //            fWhiteStart = false;
+        //            startOfIndent = false;
+        //            int startMathPosition = fCurrentPosition;
+        //            if (getNextChar('$')) {
+        //              startMathPosition = fCurrentPosition;
+        //              copyWhite(fWhiteStart, fWhiteStartPosition, 2);
+        //              fWhiteStart = false;
+        //              if (readUntilString("$$")) {
+        //                String mathContent = new String(fSource, startMathPosition,
+        // fCurrentPosition - startMathPosition - 2);
+        //                if (mathContent != null) {
+        //                  handleTeXMath(mathContent, false);
+        //                  continue;
+        //                }
+        //              }
+        //            } else {
+        //              if (readUntilChar('$')) {
+        //                String mathContent = new String(fSource, startMathPosition,
+        // fCurrentPosition - startMathPosition - 1);
+        //                if (mathContent != null) {
+        //                  handleTeXMath(mathContent, true);
+        //                  continue;
+        //                }
+        //              }
+        //            }
+        //            break;
+        case '{':
+          // detect macros
+          copyWhite(fWhiteStart, fWhiteStartPosition, 1);
+          fWhiteStart = false;
+          //              boolean scanBody = true;
+          int startMacroPosition = fCurrentPosition;
+          if (getNextChar('|') && handleWikipediaTable()) { // Wikipedia
+            // table
+            // syntax
+            continue;
+          } else {
+            if (readUntilChar('}')) {
+              String macroStartTag;
+
+              macroStartTag = new String(fSource, startMacroPosition, fCurrentPosition - startMacroPosition - 1);
+              if (macroStartTag != null) {
+                createMacro(startMacroPosition, macroStartTag);
+                continue;
+              }
+            }
+          }
+          break;
+        case '[':
+          int startLinkPosition = fCurrentPosition;
+          if (getNextChar('[')) { // wikipedia link style
+            startLinkPosition = fCurrentPosition;
+            copyWhite(fWhiteStart, fWhiteStartPosition, 2);
+            fWhiteStart = false;
+            if (readUntilString("]]")) {
+              String name = new String(fSource, startLinkPosition, fCurrentPosition - startLinkPosition - 2);
+              // test for suffix string
+              int temp = fCurrentPosition;
+              StringBuffer suffixBuffer = new StringBuffer();
+              try {
+                while (true) {
+                  fCurrentCharacter = fSource[fCurrentPosition++];
+                  if (!Character.isLetterOrDigit(fCurrentCharacter)) {
+                    fCurrentPosition--;
+                    break;
+                  }
+                  suffixBuffer.append(fCurrentCharacter);
+                }
+                handleWikipediaLink(name, suffixBuffer.toString());
+                continue;
+              } catch (IndexOutOfBoundsException e) {
+                fCurrentPosition = temp;
+              }
+
+              handleWikipediaLink(name, "");
+              continue;
+            }
+
+          } else {
+            copyWhite(fWhiteStart, fWhiteStartPosition, 1);
+            fWhiteStart = false;
+
+            if (readUntilChar(']')) {
+              String name = new String(fSource, startLinkPosition, fCurrentPosition - startLinkPosition - 1);
+              handleSnipLink(name);
+              continue;
+            }
+          }
+          break;
+        //                             case '1': // heading filter ?
+        //                                     int temp1Position = checkWhitespaces(fWhiteStartPosition,
+        //                                                     fCurrentPosition - 2);
+        //                                     if (temp1Position >= 0) {
+        //                                             copyWhite(fWhiteStart, fWhiteStartPosition, 1);
+        //                                             fWhiteStart = false;
+        //                                             int simpleHeader = getNextChar(' ', '.');
+        //                                             if (simpleHeader < 0) {
+        //                                                     if (getNextChar('1')) {
+        //                                                             fCurrentPosition--;
+        //                                                             if (getList('1', "<ol>", "</ol>")) {
+        //                                                                     continue;
+        //                                                             }
+        //                                                     }
+        //                                                     break;
+        //                                             }
+        //                                             if (simpleHeader == 1 && !getNextChar('1')) {
+        //                                                     fCurrentPosition--;
+        //                                                     if (getList('1', "<ol>", "</ol>")) {
+        //                                                             continue;
+        //                                                     }
+        //                                                     break;
+        //                                             }
+        //                                             temp1Position = fCurrentPosition;
+        //                                             if (simpleHeader >= 0 && readUntilChar('\n')) {
+        //                                                     String heading = new String(fSource, temp1Position,
+        //                                                                     fCurrentPosition - temp1Position - 1);
+        //                                                     if (heading != null) {
+        //                                                             fResultBuffer.append("<h3 class=\"heading-");
+        //                                                             if (simpleHeader == 1) {
+        //                                                                     fResultBuffer.append("1");
+        //                                                             } else {
+        //                                                                     fResultBuffer.append("1-1");
+        //                                                             }
+        //                                                             fResultBuffer.append("\">");
+        //                                                             // System.out.println(heading);
+        //                                                             fResultBuffer
+        //                                                                             .append(WikipediaFilter
+        //                                                                                             .filterParser(
+        //                                                                                                             heading,
+        //                                                                                                             fContext,
+        //                                                                                                             WikipediaFilter.DUMMY_CACHED_PAGE,
+        //                                                                                                             fMacros,
+        //                                                                                                             fRecursionLevel));
+        //                                                             fResultBuffer.append("</h3>");
+        //                                                             continue;
+        //                                                     }
+        //                                             }
+        //                                     }
+        //                                     break;
+        case '*': // <ul> list
+        case '#': // <ol> list
+          if (isStartOfLine()) {
+            char[] listChars = getListChars();
+            int tempStarPosition = checkWhitespaces(fWhiteStartPosition, fCurrentPosition - 1 - listChars.length);
+            if (tempStarPosition >= 0) {
+              appendList(listChars);
+              continue;
+            }
+          }
+          break;
+        //        case '#': // <ol> list
+        //          if (fCurrentPosition >= 2) {
+        //            char beforeChar = fSource[fCurrentPosition - 2];
+        //            if (beforeChar == '\n' || beforeChar == '\r') {
+        //
+        //              int levelHash = getNumberOfChar('#') + 1;
+        //
+        //              int tempHashPosition = checkWhitespaces(fWhiteStartPosition, fCurrentPosition - 1 - levelHash);
+        //              if (tempHashPosition >= 0) {
+        //                copyWhite(fWhiteStart, fWhiteStartPosition, levelHash);
+        //                fWhiteStart = false;
+        //                AbstractTag tok = (AbstractTag) fTokenStack.peek();
+        //                if (tok instanceof ListToken) {
+        //                  ListToken listToken = (ListToken) tok;
+        //                  int topLevel = listToken.getLevel();
+        //                  if (listToken.getToken() == WikipediaFilter.TokenLIST_OL_START) {
+        //                    if (levelHash > topLevel) {
+        //                      fTokenStack.push(new ListToken(WikipediaFilter.TokenLIST_OL_START, topLevel + 1));
+        //                      fResultBuffer.append("<ol><li>");
+        //                    } else if (levelHash < topLevel) {
+        //                      fTokenStack.pop();
+        //                      fResultBuffer.append("</li></ol></li><li>");
+        //                    } else {
+        //                      fResultBuffer.append("</li><li>");
+        //                    }
+        //                  } else {
+        //                    fTokenStack.push(new ListToken(WikipediaFilter.TokenLIST_OL_START, levelHash));
+        //                    fResultBuffer.append("<ol><li>");
+        //                  }
+        //                } else {
+        //                  fTokenStack.push(new ListToken(WikipediaFilter.TokenLIST_OL_START, 1));
+        //                  fResultBuffer.append("\n<ol><li>");
+        //                }
+        //                continue;
+        //              }
+        //            }
+        //            // }
+        //          }
+        //          break;
+
+        //                             case 'i': // <ol> list
+        //                                     if (getList('i', "<ol class=\"roman\">", "</ol>")) {
+        //                                             continue;
+        //                                     }
+        //                                     break;
+        //                             case 'I': // <ol> list
+        //                                     if (getList('i', "<ol class=\"ROMAN\">", "</ol>")) {
+        //                                             continue;
+        //                                     }
+        //                                     break;
+        //            case 'a' : // <ol> list
+        //              if (getList('a', "<ol class=\"alpha\">", "</ol>")) {
+        //                continue;
+        //              }
+        //              break;
+        //            case 'A' : // <ol> list
+        //              if (getList('A', "<ol class=\"ALPHA\">", "</ol>")) {
+        //                continue;
+        //              }
+        //              break;
+        //            case 'g' : // <ol> list
+        //              if (getList('g', "<ol class=\"greek\">", "</ol>")) {
+        //                continue;
+        //              }
+        //              break;
+        //            case 'H' : // <ol> list
+        //              if (getList('H', "<ol class=\"HIRAGANA\">", "</ol>")) {
+        //                continue;
+        //              }
+        //              break;
+        //            case 'k' : // <ol> list
+        //              if (getList('k', "<ol class=\"katakana\">", "</ol>")) {
+        //                continue;
+        //              }
+        //              break;
+        //            case 'K' : // <ol> list
+        //              if (getList('K', "<ol class=\"KATAKANA\">", "</ol>")) {
+        //                continue;
+        //              }
+        //              break;
+        //            case 'j' : // <ol> list
+        //              if (getList('j', "<ol class=\"HEBREW\">", "</ol>")) {
+        //                continue;
+        //              }
+        //              break;
+
+        case '\'':
+          if (getNextChar('\'')) {
+            if (getNextChar('\'')) {
+              copyWhite(fWhiteStart, fWhiteStartPosition, 3);
+              fWhiteStart = false;
+              return WikipediaFilter.TokenSTRONG;
+            }
+            copyWhite(fWhiteStart, fWhiteStartPosition, 2);
+            fWhiteStart = false;
+            return WikipediaFilter.TokenEM;
+          }
+          break;
+        //                             case '_':
+        //                                     if (getNextChar('_')) {
+        //                                             copyWhite(fWhiteStart, fWhiteStartPosition, 2);
+        //                                             fWhiteStart = false;
+        //                                             return WikipediaFilter.TokenBOLD;
+        //                                     }
+        //                                     break;
+        //                             case '~':
+        //                                     if (getNextChar('~')) {
+        //                                             copyWhite(fWhiteStart, fWhiteStartPosition, 2);
+        //                                             fWhiteStart = false;
+        //                                             return WikipediaFilter.TokenITALIC;
+        //                                     }
+        //                                     break;
+        case '-':
+          int tempCurrPosition = fCurrentPosition;
+          try {
+            if (fSource[tempCurrPosition++] == '-' && fSource[tempCurrPosition++] == '-' && fSource[tempCurrPosition++] == '-') {
+              if (fSource[tempCurrPosition] == '\n') {
+                fCurrentPosition = tempCurrPosition;
+                fResultBuffer.append("<hr/>");
+                fWhiteStart = false;
+                continue;
+              } else if (fSource[tempCurrPosition++] == '\r' && fSource[tempCurrPosition++] == '\n') {
+                fCurrentPosition = tempCurrPosition - 1;
+                fResultBuffer.append("<hr/>");
+                fWhiteStart = false;
+                continue;
+              }
+            }
+          } catch (IndexOutOfBoundsException e) {
+
+          }
+
+          //                                   int levelMinus = getNumberOfChar('-') + 1;
+          //                                   if (getNextChar(' ')) {
+          //                                           int tempPosition = checkWhitespaces(
+          //                                                           fWhiteStartPosition, fCurrentPosition - 2
+          //                                                                           - levelMinus);
+          //                                           if (tempPosition >= 0) {
+          //                                                   copyWhite(fWhiteStart, fWhiteStartPosition,
+          //                                                                   1 + levelMinus);
+          //                                                   fWhiteStart = false;
+          //                                                   AbstractTag tok = (AbstractTag) fTokenStack.peek();
+          //                                                   if (tok instanceof ListToken) {
+          //                                                           ListToken listToken = (ListToken) tok;
+          //                                                           int topLevel = listToken.getLevel();
+          //                                                           if (listToken.getToken() ==
+          // WikipediaFilter.TokenLIST_UL_START) {
+          //                                                                   if (levelMinus > topLevel) {
+          //                                                                           fTokenStack
+          //                                                                                           .push(new ListToken(
+          //                                                                                                           WikipediaFilter.TokenLIST_UL_START,
+          //                                                                                                           topLevel + 1));
+          //                                                                           fResultBuffer
+          //                                                                                           .append("<ul class=\"minus\"><li>");
+          //                                                                   } else if (levelMinus < topLevel) {
+          //                                                                           fTokenStack.pop();
+          //                                                                           fResultBuffer
+          //                                                                                           .append("</li></ul></li><li>");
+          //                                                                   } else {
+          //                                                                           fResultBuffer.append("</li><li>");
+          //                                                                   }
+          //                                                           } else {
+          //                                                                   fTokenStack
+          //                                                                                   .push(new ListToken(
+          //                                                                                                   WikipediaFilter.TokenLIST_UL_START,
+          //                                                                                                   levelMinus));
+          //                                                                   fResultBuffer
+          //                                                                                   .append("<ul class=\"minus\"><li>");
+          //                                                           }
+          //                                                   } else {
+          //                                                           fTokenStack
+          //                                                                           .push(new ListToken(
+          //                                                                                           WikipediaFilter.TokenLIST_UL_START,
+          //                                                                                           1));
+          //                                                           fResultBuffer
+          //                                                                           .append("\n<ul class=\"minus\"><li>");
+          //                                                   }
+          //                                                   continue;
+          //                                           }
+          //                                   }
+          //                                   if (levelMinus == 2) {
+          //                                           copyWhite(fWhiteStart, fWhiteStartPosition, 2);
+          //                                           fWhiteStart = false;
+          //                                           return WikipediaFilter.TokenSTRIKETHROUGH;
+          //                                   }
+          break;
+        case 'h': // http(s)://
+          int urlStartPosition = fCurrentPosition;
+          boolean foundUrl = false;
+          int diff = 7;
+          try {
+            String urlString = fStringSource.substring(fCurrentPosition - 1, fCurrentPosition + 3);
+            if (urlString.equals("http")) {
+              fCurrentPosition += 3;
+              fCurrentCharacter = fSource[fCurrentPosition++];
+              if (fCurrentCharacter == 's') { // optional
+                fCurrentCharacter = fSource[fCurrentPosition++];
+                diff++;
+              }
+
+              if (fCurrentCharacter == ':' && fSource[fCurrentPosition++] == '/' && fSource[fCurrentPosition++] == '/') {
+                copyWhite(fWhiteStart, fWhiteStartPosition, diff);
+                fWhiteStart = false;
+                foundUrl = true;
+                while (WikipediaFilter.isUrlIdentifierPart(fSource[fCurrentPosition++])) {
+                }
+              }
+            }
+          } catch (IndexOutOfBoundsException e) {
+            if (!foundUrl) {
+              //              rollback work :-)
+              fCurrentPosition = urlStartPosition;
+            }
+          }
+          if (foundUrl) {
+            String urlString = new String(fSource, urlStartPosition - 1, fCurrentPosition - urlStartPosition);
+            fCurrentPosition--;
+            WikipediaFilter.createExternalLink(fResultBuffer, fWikiEngine, urlString);
+            continue;
+          }
+          break;
+
+        //        case '@': // images @xml@ -> /static/rss-small.png
+        //          copyWhite(fWhiteStart, fWhiteStartPosition, 1);
+        //          fWhiteStart = false;
+        //          int atStart = fCurrentPosition;
+        //          if (readUntilChar('@')) {
+        //            String imageTag = new String(fSource, atStart, fCurrentPosition - atStart - 1);
+        //            if (imageTag != null) {
+        //              if (WikipediaFilter.createStaticImage(imageTag, fResultBuffer)) {
+        //                continue;
+        //              }
+        //            }
+        //          }
+        //          fCurrentPosition = atStart;
+        //          break;
+        case '&':
+          int ampersandStart = fCurrentPosition - 1;
+          if (getNextChar('#')) {
+            try {
+              StringBuffer num = new StringBuffer(5);
+              char ch = fSource[fCurrentPosition++];
+              while (Character.isDigit(ch)) {
+                num.append(ch);
+                ch = fSource[fCurrentPosition++];
+              }
+              if (num.length() > 0 && ch == ';') {
+                Integer i = Integer.valueOf(num.toString());
+                if (i.intValue() < 65536) {
+                  copyWhite(fWhiteStart, fWhiteStartPosition, 3 + num.length());
+                  fWhiteStart = false;
+                  fResultBuffer.append(fSource, ampersandStart, fCurrentPosition - ampersandStart);
+                  continue;
+                }
+              }
+            } catch (IndexOutOfBoundsException e) {
+              // ignore exception
+            } catch (NumberFormatException e) {
+              // ignore exception
+            }
+          } else {
+            try {
+              StringBuffer entity = new StringBuffer(10);
+              char ch = fSource[fCurrentPosition++];
+              while (Character.isLetterOrDigit(ch)) {
+                entity.append(ch);
+                ch = fSource[fCurrentPosition++];
+              }
+              if (entity.length() > 0 && ch == ';') {
+                if (WikipediaFilter.ENTITY_SET.contains(entity.toString())) {
+                  copyWhite(fWhiteStart, fWhiteStartPosition, 2 + entity.length());
+                  fWhiteStart = false;
+                  fResultBuffer.append(fSource, ampersandStart, fCurrentPosition - ampersandStart);
+                  continue;
+                }
+              }
+            } catch (IndexOutOfBoundsException e) {
+              // ignore exception
+            } catch (NumberFormatException e) {
+              // ignore exception
+            }
+          }
+          break;
+        case '<':
+          int htmlStartPosition = fCurrentPosition;
+          try {
+            switch (fStringSource.charAt(fCurrentPosition)) {
+            case '!': // <!-- html comment -->
+              String htmlCommentString = fStringSource.substring(fCurrentPosition - 1, fCurrentPosition + 3);
+
+              if (htmlCommentString.equals("<!--")) {
+                fCurrentPosition += 3;
+                if (readUntilString("-->")) {
+                  String htmlCommentContent = new String(fSource, htmlStartPosition + 3, fCurrentPosition - htmlStartPosition - 6);
+                  if (htmlCommentContent != null) {
+                    copyWhite(fWhiteStart, fWhiteStartPosition, fCurrentPosition - htmlStartPosition + 1);
+                    fWhiteStart = false;
+                    // insert html comment for visual checks
+                    // only:
+                    /*
+                     * fResultBuffer.append(" <!--"); copyWhite(htmlCommentContent); fResultBuffer.append("--> ");
+                     */
+                    continue;
+                  }
+                }
+              }
+              break;
+            //                case 'm' : // math
+            //                  String mathString =
+            // fStringSource.substring(fCurrentPosition - 1,
+            // fCurrentPosition + 5);
+
+            //                  if (mathString.equals("<math>")) {
+            //                    fCurrentPosition += 5;
+            //                    if (readUntilString("</math>")) {
+            //                      String mathContent = new String(fSource,
+            // htmlStartPosition + 5, fCurrentPosition -
+            // htmlStartPosition - 12);
+            //                      if (mathContent != null) {
+            //                        copyWhite(fWhiteStart, fWhiteStartPosition,
+            // fCurrentPosition - htmlStartPosition + 1);
+            //                        fWhiteStart = false;
+            //                        if (startOfIndent) {
+            //                          startOfIndent = false;
+            //                          handleTeXMath(mathContent, false);
+            //                        } else {
+            //                          handleTeXMath(mathContent, true);
+            //                        }
+            //                        continue;
+            //                      }
+            //                    }
+            //                  }
+            //                  break;
+            case 'n': // nowiki
+              String nowikiString = fStringSource.substring(fCurrentPosition - 1, fCurrentPosition + 7);
+
+              if (nowikiString.equals("<nowiki>")) {
+                fCurrentPosition += 7;
+                if (readUntilString("</nowiki>")) {
+                  String nowikiContent = new String(fSource, htmlStartPosition + 7, fCurrentPosition - htmlStartPosition - 16);
+                  if (nowikiContent != null) {
+                    copyWhite(fWhiteStart, fWhiteStartPosition, fCurrentPosition - htmlStartPosition + 1);
+                    fWhiteStart = false;
+                    copyNowikiNewLine(nowikiContent);
+                    continue;
+                  }
+                }
+              }
+              break;
+            }
+          } catch (IndexOutOfBoundsException e) {
+
+          }
+          startOfIndent = false;
+          fCurrentPosition = htmlStartPosition;
+          // detect special html tags
+          int htmlToken = getHTMLToken();
+          if (htmlToken == WikipediaFilter.TokenIgnore) {
+            continue;
+            //              } else if (htmlToken > TokenIgnore) {
+            //                return htmlToken;
+          }
+          fCurrentPosition = htmlStartPosition;
+          break;
+        case '=': // wikipedia header ?
+          if (isStartOfLine()) {
+            int levelHeader = getNumberOfChar('=') + 1;
+            //            int tempPosition = checkWhitespaces(fWhiteStartPosition, fCurrentPosition - 1 - levelHeader);
+            //            if (tempPosition >= 0) {
+            copyWhite(fWhiteStart, fWhiteStartPosition, levelHeader);
+            fWhiteStart = false;
+            int startHeadPosition = fCurrentPosition;
+            //                 int initialOffset = levelHeader;
+            if (levelHeader > 6) {
+              levelHeader = 6;
+            }
+            levelHeader--;
+            if (readUntilString(WikipediaFilter.HEADER_STRINGS[levelHeader])) {
+              String head = new String(fSource, startHeadPosition, fCurrentPosition - startHeadPosition - (1 + levelHeader));
+              levelHeader++;
+              handleHead(head, levelHeader);
+              continue;
+            }
+            //            }
+          }
+          break;
+        }
+        if (!fWhiteStart) {
+          fWhiteStart = true;
+          fWhiteStartPosition = fCurrentPosition - 1;
+        }
+
+        startOfIndent = false;
+      }
+      //    -----------------end switch while try--------------------
+    } catch (IndexOutOfBoundsException e) {
+      // end of scanner text
+    }
+    copyWhite(fWhiteStart, fWhiteStartPosition, 1);
+
+    return WikipediaFilter.TokenEOF;
+  }
+
+  /**
+   * @return
+   */
+  private boolean isStartOfLine() {
+    boolean isListStart = false;
+    if (fCurrentPosition >= 2) {
+      char beforeChar = fSource[fCurrentPosition - 2];
+      if (beforeChar == '\n' || beforeChar == '\r') {
+        isListStart = true;
+      }
+    }
+    if (fCurrentPosition == 1) {
+      isListStart = true;
+    }
+    return isListStart;
+  }
+
+  /**
+   * @param levelStar
+   * @param listChars
+   *          TODO
+   */
+  private void appendList(char[] listChars) {
+    int topLevel = 0;
+    int levelStar = listChars.length;
+    copyWhite(fWhiteStart, fWhiteStartPosition, levelStar);
+    fWhiteStart = false;
+    AbstractTag tok = (AbstractTag) fTokenStack.peek();
+
+    if (tok instanceof ListToken) {
+      ListToken listToken = (ListToken) tok;
+      topLevel = listToken.getLevel();
+
+      if (levelStar > topLevel) {
+        while (levelStar > topLevel) {
+          if (listChars[topLevel] == '*') {
+            fTokenStack.push(new ListToken(WikipediaFilter.TokenLIST_UL_START, ++topLevel));
+            fResultBuffer.append("<ul><li>");
+          } else {
+            fTokenStack.push(new ListToken(WikipediaFilter.TokenLIST_OL_START, ++topLevel));
+            fResultBuffer.append("<ol><li>");
+          }
+        }
+      } else if (levelStar < topLevel) {
+        while (levelStar < topLevel) {
+          tok = (AbstractTag) fTokenStack.peek();
+          if (tok instanceof ListToken) {
+            fTokenStack.pop();
+            listToken = (ListToken) tok;
+            if (listToken.getToken() == WikipediaFilter.TokenLIST_UL_START) {
+              fResultBuffer.append("</li></ul></li><li>");
+            } else {
+              fResultBuffer.append("</li></ol></li><li>");
+            }
+            topLevel--;
+          } else {
+            break;
+          }
+        }
+      } else {
+        --topLevel;
+        if (listToken.getToken() == WikipediaFilter.TokenLIST_UL_START && listChars[topLevel] == '#') {
+          fTokenStack.pop();
+          fTokenStack.push(new ListToken(WikipediaFilter.TokenLIST_OL_START, topLevel));
+          fResultBuffer.append("</li></ul><ol><li>");
+        } else if (listToken.getToken() == WikipediaFilter.TokenLIST_OL_START && listChars[topLevel] == '*') {
+          fTokenStack.pop();
+          fTokenStack.push(new ListToken(WikipediaFilter.TokenLIST_UL_START, topLevel));
+          fResultBuffer.append("</li></ol><ul><li>");
+        } else {
+          fResultBuffer.append("</li><li>");
+        }
+      }
+    } else {
+      while (levelStar > topLevel) {
+        if (listChars[topLevel] == '*') {
+          fTokenStack.push(new ListToken(WikipediaFilter.TokenLIST_UL_START, ++topLevel));
+          fResultBuffer.append("\n<ul><li>");
+        } else {
+          fTokenStack.push(new ListToken(WikipediaFilter.TokenLIST_OL_START, ++topLevel));
+          fResultBuffer.append("\n<ol><li>");
+        }
+      }
+    }
+  }
+
+  private void createMacro(int startMacroPosition, String macroStartTag) {
+    String command = "";
+    String endTag;
+
+    String parameterString = null;
+    String macroBodyString = "";
+    int index0;
+    int index1;
+    if ((index0 = macroStartTag.indexOf(':')) >= 0) {
+      command = macroStartTag.substring(0, index0);
+      parameterString = macroStartTag.substring(index0 + 1, macroStartTag.length());
+    } else {
+      command = macroStartTag;
+    }
+    Macro macro = (Macro) fMacros.get(command);
+
+    String completeMacroSubString;
+
+    if ((macro != null) && (macro instanceof IBodyTagSupportMacro)) {
+      endTag = '{' + command + '}';
+      index0 = fStringSource.indexOf(endTag, fCurrentPosition);
+
+      if (index0 >= 0) {
+        macroBodyString = fStringSource.substring(fCurrentPosition, index0);
+        completeMacroSubString = new String(fSource, startMacroPosition - 1, index0 + endTag.length() - startMacroPosition + 1);
+        fCurrentPosition = startMacroPosition + completeMacroSubString.length() - 1;
+      } else {
+        completeMacroSubString = new String(fSource, startMacroPosition - 1, macroStartTag.length() + 2);
+      }
+    } else {
+      completeMacroSubString = new String(fSource, startMacroPosition - 1, macroStartTag.length() + 2);
+    }
+
+    copyWhite(fWhiteStart, fWhiteStartPosition, 1);
+
+    handleMacro(completeMacroSubString, command, parameterString, macroBodyString);
+  }
+
+  //  private void createExternalLink(String urlString) {
+  //
+  //    // Does our engine know images?
+  //    if (fWikiEngine instanceof ImageRenderEngine) {
+  //      fResult.append(((ImageRenderEngine) fWikiEngine).getExternalImageLink());
+  //    }
+  //    fResult.append("<span class=\"nobr\">");
+  //    fResult.append("<a href=\"");
+  //    fResult.append(Encoder.escape(urlString));
+  //    fResult.append("\">");
+  //    fResult.append(Encoder.toEntity(urlString.charAt(0)) +
+  // urlString.substring(1));
+  //    fResult.append("</a></span>");
+  //  }
+
+  //  private void handleTeXMath(String mathContent, boolean inlineExpression)
+  // {
+  //    // TODO clean this up
+  //    Map map = Application.get().getParameters();
+  //    HttpServletRequest request = (HttpServletRequest) map.get("request");
+  //    MathSniffer sniffy = MathSniffer.getBrowserDetection(request);
+  //
+  //    if (fCacheStaticBlockActive) {
+  //      fCachedPage.addHTML(fResultBuffer.substring(fCacheStaticBlockStartPosition,
+  // fResultBuffer.length()));
+  //      fCacheStaticBlockActive = false;
+  //    }
+  //    // if (inlineExpression) {
+  //    // fASMCompiler.compileMath(mathContent, "true");
+  //    // } else {
+  //    // fASMCompiler.compileMath(mathContent, "false");
+  //    // }
+  //    if (fCachedPage == WikipediaFilter.DUMMY_CACHED_PAGE) {
+  //      switch (sniffy.getBrowserId()) {
+  //        case MathSniffer.XMLID :
+  //        case MathSniffer.MATHPLAYERID :
+  //          if (inlineExpression) {
+  //            fResultBuffer.append("<m:math><m:mstyle mathcolor=\"Black\"
+  // displaystyle=\"true\">");
+  //            fTeXParser.initialize(mathContent);
+  //            fTeXParser.parse2MML(fResultBuffer);
+  //            fResultBuffer.append("</m:mstyle></m:math>");
+  //          } else {
+  //            fResultBuffer.append("<dl><dd><m:math><m:mstyle mathcolor=\"Black\"
+  // displaystyle=\"true\">");
+  //            fTeXParser.initialize(mathContent);
+  //            fTeXParser.parse2MML(fResultBuffer);
+  //            fResultBuffer.append("</m:mstyle></m:math></dd></dl>");
+  //          }
+  //          break;
+  //        case MathSniffer.CSSID :
+  //          if (inlineExpression) {
+  //            fResultBuffer.append("<m>");
+  //            fTeXParser.initialize(mathContent);
+  //            fTeXParser.parse2CSS(fResultBuffer, true);
+  //            fResultBuffer.append("</m>");
+  //          } else {
+  //            fResultBuffer.append("<e>");
+  //            fTeXParser.initialize(mathContent);
+  //            fTeXParser.parse2CSS(fResultBuffer, true);
+  //            fResultBuffer.append("</e>");
+  //          }
+  //          break;
+  //        default :
+  //          copyWhite(mathContent);
+  //      }
+  //    } else {
+  //      String[] mathStrings = new String[3];
+  //      StringBuffer mathBuffer = new StringBuffer();
+  //      if (inlineExpression) {
+  //        // mathml inline
+  //        mathBuffer.append("<m:math><m:mstyle mathcolor=\"Black\"
+  // displaystyle=\"true\">");
+  //
+  //        fTeXParser.initialize(mathContent);
+  //        fTeXParser.parse2MML(mathBuffer);
+  //        mathBuffer.append("</m:mstyle></m:math>");
+  //      } else {
+  //        mathBuffer.append("<dl><dd><m:math><m:mstyle mathcolor=\"Black\"
+  // displaystyle=\"true\">");
+  //        fTeXParser.initialize(mathContent);
+  //        fTeXParser.parse2MML(mathBuffer);
+  //        mathBuffer.append("</m:mstyle></m:math></dd></dl>");
+  //      }
+  //      mathStrings[0] = mathBuffer.toString();
+  //      mathBuffer.setLength(0);
+  //      // if (inlineExpression) {
+  //      // // css inline
+  //      // mathBuffer.append("<m>");
+  //      // fTeXParser.initialize(mathContent);
+  //      // fTeXParser.parse2CSS(mathBuffer, true);
+  //      // mathBuffer.append("</m>");
+  //      // } else {
+  //      // // css block mode
+  //      // mathBuffer.append("<e>");
+  //      // fTeXParser.initialize(mathContent);
+  //      // fTeXParser.parse2CSS(mathBuffer, true);
+  //      // mathBuffer.append("</e>");
+  //      // }
+  //
+  //      String encodedMathContent = Encoder.escape(mathContent);
+  //      StringBuffer mathmlBuffer = new StringBuffer();
+  //      String shortImageName = "____tex_" + (fImageCounter++);
+  //      String longImageName = shortImageName + ".gif";
+  //      mathmlBuffer.append("<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>");
+  //      if (inlineExpression) {
+  //        mathmlBuffer.append("<math><mstyle mathcolor=\"Black\"
+  // displaystyle=\"true\">");
+  //        fTeXImageParser.initialize(mathContent);
+  //        fTeXImageParser.parse2MML(mathmlBuffer);
+  //        mathmlBuffer.append("</mstyle></math>");
+  //      } else {
+  //        mathmlBuffer.append("<math><mstyle mathcolor=\"Black\"
+  // displaystyle=\"true\">");
+  //        fTeXImageParser.initialize(mathContent);
+  //        fTeXImageParser.parse2MML(mathmlBuffer);
+  //        mathmlBuffer.append("</mstyle></math>");
+  //      }
+  //
+  //      String snipname = fSnip.getName();
+  //      String SnipSnapSpacePath =
+  // Application.get().getConfiguration().getFilePath().getAbsolutePath();
+  //      // Remove old image
+  //      fSnip.getAttachments().removeAttachment(longImageName + ".gif");
+  //
+  //      String directoryName = SnipSnapSpacePath + "/" + snipname;
+  //      File directory = new File(directoryName);
+  //      if (!directory.exists()) {
+  //        directory.mkdirs();
+  //      }
+  //      String gifFilename = directoryName + "/" + longImageName;
+  //      // File file = new File();
+  //      // Get the number of bytes in the file
+  //      // long length = file.length();
+  //      MathMLToGIFConverter conv = new MathMLToGIFConverter();
+  //      // String test =
+  //      // "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?><math
+  //      //
+  // mode=\"display\"><mrow><munderover><mo>&#x0222B;</mo><mn>1</mn><mi>x</mi></munderover><mfrac><mi>dt</mi><mi>t</mi></mfrac></mrow></math>";
+  //      try {
+  //        File imageFile = conv.convert(mathmlBuffer.toString(), gifFilename);
+  //        if (imageFile != null) {
+  //          Attachment attachment =
+  //            new Attachment(longImageName, "image/gif", imageFile.length(), new
+  // Date(), snipname + "/" + longImageName, true);
+  //          // fSnip.getAttachments().addAttachment(longImageName, "image/gif",
+  // imageFile.length(), snipname + "/" + longImageName,
+  //          // true);
+  //          fSnip.getAttachments().addAttachment(attachment);
+  //          StringWriter writer = new StringWriter();
+  //
+  //          SnipLink.appendImage(writer, fSnip, shortImageName, encodedMathContent,
+  // "gif", null);
+  //
+  //          mathBuffer = writer.getBuffer();
+  //          mathStrings[1] = mathBuffer.toString();
+  //        } else {
+  //          mathStrings[1] = encodedMathContent;
+  //        }
+  //      } catch (IOException e) {
+  //        // TODO Auto-generated catch block
+  //        e.printStackTrace();
+  //        mathStrings[1] = encodedMathContent;
+  //      }
+  //      mathBuffer.setLength(0);
+  //      WikipediaFilter.copyWhite(mathBuffer, mathContent);
+  //      mathStrings[2] = mathBuffer.toString();
+  //      fCachedPage.addMath(mathStrings);
+  //    }
+  //    if (!fCacheStaticBlockActive) {
+  //      fCacheStaticBlockActive = true;
+  //      fCacheStaticBlockStartPosition = fResultBuffer.length();
+  //    }
+  //  }
+  private void handleSnipLink(String name) {
+    if (name != null) {
+      int index = name.indexOf("http://");
+      // Configuration probably wrote [http://radeox.org] instead of
+      // http://radeox.org
+      if (index != -1) {
+        // WikipediaFilter.createExternalLink(fResultBuffer,
+        // fWikiEngine, name.substring(index));
+        String urlString = name.substring(index);
+        // Wikipedia like style:
+        int pipeIndex = urlString.indexOf(' ');
+        String alias = "";
+        if (pipeIndex != (-1)) {
+          alias = urlString.substring(pipeIndex + 1);
+          urlString = urlString.substring(0, pipeIndex);
+        } else {
+          alias = urlString;
+        }
+
+        if (fWikiEngine instanceof ImageRenderEngine) {
+          fResultBuffer.append(((ImageRenderEngine) fWikiEngine).getExternalImageLink());
+        }
+        fResultBuffer.append("<span class=\"nobr\">");
+        fResultBuffer.append("<a href=\"");
+        fResultBuffer.append(Encoder.escape(urlString));
+        fResultBuffer.append("\">");
+        fResultBuffer.append(Encoder.toEntity(alias.charAt(0)) + alias.substring(1));
+        fResultBuffer.append("</a></span>");
+      }
+      //      else {
+      //        // trim the name and unescape it
+      //        name = Encoder.unescape(name.trim());
+      //        // Is there an alias like [alias|link] ?
+      //        int pipeIndex = name.indexOf('|');
+      //        String alias = "";
+      //        if (-1 != pipeIndex) {
+      //          alias = name.substring(0, pipeIndex);
+      //          name = name.substring(pipeIndex + 1);
+      //        }
+      //
+      //        int hashIndex = name.lastIndexOf('#');
+      //
+      //        String hash = "";
+      //        if (-1 != hashIndex && hashIndex != name.length() - 1) {
+      //          hash = name.substring(hashIndex + 1);
+      //          name = name.substring(0, hashIndex);
+      //        }
+      //
+      //        int colonIndex = name.indexOf(':');
+      //        // typed link ?
+      //        if (-1 != colonIndex) {
+      //          // for now throw away the fType information
+      //          name = name.substring(colonIndex + 1);
+      //        }
+      //
+      //        int atIndex = name.lastIndexOf('@');
+      //        // InterWiki link ?
+      //        if (-1 != atIndex) {
+      //          String extSpace = name.substring(atIndex + 1);
+      //          // known extarnal space ?
+      //          InterWiki interWiki = InterWiki.getInstance();
+      //          if (interWiki.contains(extSpace)) {
+      //            name = name.substring(0, atIndex);
+      //            Writer writer = new StringBufferWriter(fResultBuffer);
+      //            try {
+      //              if (-1 != hashIndex) {
+      //                interWiki.expand(writer, extSpace, name, hash);
+      //              } else {
+      //                interWiki.expand(writer, extSpace, name, "");
+      //              }
+      //            } catch (IOException e) {
+      //              log.debug("InterWiki " + extSpace + " not found.");
+      //            }
+      //          } else {
+      //            fResultBuffer.append("&#91;<span class=\"error\">");
+      //            fResultBuffer.append(name);
+      //            fResultBuffer.append("?</span>&#93;");
+      //          }
+      //        } else {
+      //          // internal link
+      //          if (fWikiEngine != null && fWikiEngine instanceof WikiRenderEngine) {
+      //            if (fCacheStaticBlockActive) {
+      //              fCachedPage.addHTML(fResultBuffer.substring(fCacheStaticBlockStartPosition, fResultBuffer.length()));
+      //              fCacheStaticBlockActive = false;
+      //            }
+      //            fCachedPage.addSnipLink(name);
+      //            if (fCachedPage == WikipediaFilter.DUMMY_CACHED_PAGE) {
+      //              if (((WikiRenderEngine) fWikiEngine).exists(name)) {
+      //                String view = name;
+      //                if (-1 != pipeIndex) {
+      //                  view = alias;
+      //                }
+      //                // Do not add hash if an alias was given
+      //                if (-1 != hashIndex) {
+      //                  ((WikiRenderEngine) fWikiEngine).appendLink(fResultBuffer, name, view, hash);
+      //                } else {
+      //                  ((WikiRenderEngine) fWikiEngine).appendLink(fResultBuffer, name, view);
+      //                }
+      //              } else if (((WikiRenderEngine) fWikiEngine).showCreate()) {
+      //                ((WikiRenderEngine) fWikiEngine).appendCreateLink(fResultBuffer, name, name);
+      //                // links with "create" are not cacheable because
+      //                // a missing wiki could be created
+      //                fContext.getRenderContext().setCacheable(false);
+      //              } else {
+      //                // cannot display/create wiki, so just display
+      //                // the text
+      //                fResultBuffer.append(name);
+      //              }
+      //            }
+      //            if (!fCacheStaticBlockActive) {
+      //              fCacheStaticBlockActive = true;
+      //              fCacheStaticBlockStartPosition = fResultBuffer.length();
+      //            }
+      //          } else {
+      //            // cannot display/create wiki, so just display the text
+      //            fResultBuffer.append(name);
+      //          }
+      //        }
+      //      }
+    }
+  }
+
+  private boolean handleWikipediaTable() {
+    //  // example
+    //// {| border=1
+    //// |Zelle 1
+    //// |
+    //// {| border=2
+    //// |Zelle A
+    //// |-
+    //// |Zelle B
+    //// |}
+    //// |Zelle 3
+    //// |}
+    int temp = fCurrentPosition;
+    int sequenceStart = 0;
+    char lastChar = ' ';
+    int sequenceLength = 0;
+    int thStartPosition = 0;
+    Stack wpTokenStack = new Stack();
+    try {
+      // add table attributes:
+      fResultBuffer.append("<table ");
+      sequenceStart = fCurrentPosition;
+      fCurrentCharacter = fSource[fCurrentPosition++];
+      while (fCurrentCharacter != '\n' && fCurrentCharacter != '\r') {
+        sequenceLength++;
+        fCurrentCharacter = fSource[fCurrentPosition++];
+      }
+      if (fCurrentCharacter == '\n' || fCurrentCharacter == '\r') {
+        fCurrentCharacter = fSource[fCurrentPosition++];
+      }
+      if (sequenceLength > 0) {
+        fResultBuffer.append(fSource, sequenceStart + 1, sequenceLength - 1);
+      }
+      fResultBuffer.append(">");
+      wpTokenStack.push(WikipediaFilter.HTML_TABLE_OPEN);
+
+      fResultBuffer.append("<tr>\n");
+      wpTokenStack.push(WikipediaFilter.HTML_TR_OPEN);
+      String attributes = null;
+      // parse rest of table
+      while (true) {
+        sequenceStart = fCurrentPosition;
+        fCurrentCharacter = fSource[fCurrentPosition++];
+        if (fCurrentCharacter == '{' && fSource[fCurrentPosition] == '|') { // nested table
+          handleWikipediaTable();
+        } else if (fCurrentCharacter == '!') {
+          // <th>...</th>
+          reduceTableCellStack(fResultBuffer, wpTokenStack);
+          fResultBuffer.append(fSource, sequenceStart, fCurrentPosition - sequenceStart - 1);
+          sequenceStart = fCurrentPosition;
+          // add header row cells
+          attributes = null;
+          while (true) {
+            fCurrentCharacter = fSource[fCurrentPosition++];
+            if (fCurrentCharacter == '|' || fCurrentCharacter == '\n') {
+              if (fSource[fCurrentPosition] == '|' || fCurrentCharacter == '\n') {
+                reduceTableCellStack(fResultBuffer, wpTokenStack);
+                if (attributes == null) {
+                  fResultBuffer.append("<th>");
+                } else {
+                  fResultBuffer.append("<th ");
+                  fResultBuffer.append(attributes);
+                  fResultBuffer.append(">");
+                }
+                wpTokenStack.push(WikipediaFilter.HTML_TH_OPEN);
+                fResultBuffer.append(WikipediaFilter.filterParser(new String(fSource, sequenceStart, fCurrentPosition
+                    - sequenceStart - 1), fContext, fMacros, fRecursionLevel));
+                fCurrentPosition++;
+                sequenceStart = fCurrentPosition;
+                attributes = null;
+              } else {
+                attributes = new String(fSource, sequenceStart, fCurrentPosition - sequenceStart - 1);
+                sequenceStart = fCurrentPosition;
+              }
+            }
+            if (fCurrentCharacter == '\n') {
+              fCurrentPosition--;
+              break;
+            }
+          }
+        } else if (fCurrentCharacter == '|') {
+          reduceTableCellStack(fResultBuffer, wpTokenStack);
+          fResultBuffer.append(fSource, sequenceStart, fCurrentPosition - sequenceStart - 1);
+
+          sequenceStart = fCurrentPosition;
+          fCurrentCharacter = fSource[fCurrentPosition++];
+          switch (fCurrentCharacter) {
+          case '+': // caption
+            sequenceStart++;
+            reduceTableRowStack(WikipediaFilter.HTML_TABLE_OPEN, fResultBuffer, wpTokenStack);
+            fResultBuffer.append("<caption>\n");
+            wpTokenStack.push(WikipediaFilter.HTML_CAPTION_OPEN);
+            // read until end of line
+            while (fCurrentCharacter != '\n' && fCurrentCharacter != '\r') {
+              fCurrentCharacter = fSource[fCurrentPosition++];
+            }
+            if (fCurrentCharacter == '\n' || fCurrentCharacter == '\r') {
+              fCurrentCharacter = fSource[fCurrentPosition++];
+            }
+            fResultBuffer.append(WikipediaFilter.filterParser(new String(fSource, sequenceStart, fCurrentPosition - sequenceStart
+                - 1), fContext, fMacros, fRecursionLevel));
+            break;
+          case '-': // new row
+            sequenceStart++;
+            reduceTableRowStack(WikipediaFilter.HTML_TR_OPEN, fResultBuffer, wpTokenStack);
+
+            // read until end of line
+            while (fCurrentCharacter != '\n' && fCurrentCharacter != '\r') {
+              fCurrentCharacter = fSource[fCurrentPosition++];
+            }
+            if (fCurrentCharacter == '\n' || fCurrentCharacter == '\r') {
+              fCurrentCharacter = fSource[fCurrentPosition++];
+            }
+            // TODO handle row attributes
+            fResultBuffer.append("<tr ");
+            wpTokenStack.push(WikipediaFilter.HTML_TR_OPEN);
+            fResultBuffer.append(fSource, sequenceStart, fCurrentPosition - sequenceStart - 1);
+            fResultBuffer.append(">\n");
+            //            fResultBuffer.append(WikipediaFilter.filterParser(new String(fSource, sequenceStart, fCurrentPosition
+            //                - sequenceStart - 1), fContext, fMacros, fRecursionLevel));
+            break;
+          case '}': // end of table
+            clearTableStack(fResultBuffer, wpTokenStack);
+            //                                         System.out.println(fResultBuffer.toString());
+            return true;
+          default:
+            // add row cells
+            attributes = null;
+            while (true) {
+              fCurrentCharacter = fSource[fCurrentPosition++];
+              if (fCurrentCharacter == '|' || fCurrentCharacter == '\n') {
+                if (fSource[fCurrentPosition] == '|' || fCurrentCharacter == '\n') {
+                  reduceTableCellStack(fResultBuffer, wpTokenStack);
+                  if (attributes == null) {
+                    fResultBuffer.append("<td>");
+                  } else {
+                    fResultBuffer.append("<td ");
+                    fResultBuffer.append(attributes);
+                    fResultBuffer.append(">");
+                  }
+                  wpTokenStack.push(WikipediaFilter.HTML_TD_OPEN);
+                  fResultBuffer.append(WikipediaFilter.filterParser(new String(fSource, sequenceStart, fCurrentPosition
+                      - sequenceStart - 1), fContext, fMacros, fRecursionLevel));
+                  // TODO reduce fTokenStack to <tr> element
+                  // if necessary
+                  //                  fResultBuffer.append("</td>");
+                  //                  fTokenStack.pop();
+                  fCurrentPosition++;
+                  sequenceStart = fCurrentPosition;
+                  attributes = null;
+                } else {
+                  attributes = new String(fSource, sequenceStart, fCurrentPosition - sequenceStart - 1);
+
+                  sequenceStart = fCurrentPosition;
+                }
+              }
+              if (fCurrentCharacter == '\n') {
+                fCurrentPosition--;
+                break;
+              }
+            }
+          }
+        } else if (wpTokenStack.peek() == WikipediaFilter.HTML_TD_OPEN) {
+          // continue a table cell in the next line
+          while (true) {
+            if (fCurrentCharacter == '\n') {
+              char ch0 = fSource[fCurrentPosition];
+              char ch1 = fSource[fCurrentPosition + 1];
+              if (ch0 == '|' || ch0 == '!' || (ch0 == '{' && ch1 == '|')) {
+                fResultBuffer.append(WikipediaFilter.filterParser(new String(fSource, sequenceStart, fCurrentPosition
+                    - sequenceStart - 1), fContext, fMacros, fRecursionLevel));
+                sequenceStart = fCurrentPosition;
+                attributes = null;
+                break;
+              }
+            }
+            fCurrentCharacter = fSource[fCurrentPosition++];
+          }
+        }
+      }
+    } catch (IndexOutOfBoundsException e) {
+      if (sequenceStart + 1 < fCurrentPosition && fSource[sequenceStart + 1] == '}') {
+        //                              TODO reduce fTokenStack to <tr> element if necessary
+        //        fResultBuffer.append("</tr></table>\n");
+        //        wpTokenStack.pop(); // tr
+        //        wpTokenStack.pop();// table
+        //                             System.out.println(fResultBuffer.toString());
+        clearTableStack(fResultBuffer, wpTokenStack);
+        return true;
+      }
+    }
+    fCurrentPosition = temp - 1;
+    //         System.out.print(fResultBuffer.toString());
+    return false;
+  } //  private boolean handleWikipediaTable() {
+
+  private void clearTableStack(StringBuffer buffer, Stack stack) {
+    CloseTagToken closeTag;
+    AbstractTag tag;
+    while (!stack.isEmpty()) {
+      tag = (AbstractTag) stack.pop();
+      closeTag = (CloseTagToken) WikipediaFilter.CLOSE_TAGS.get(tag.getTagName());
+      buffer.append(closeTag.getCloseTag());
+    }
+  }
+
+  private void reduceTableRowStack(AbstractTag stopTag, StringBuffer buffer, Stack stack) {
+    CloseTagToken closeTag;
+    AbstractTag tag;
+    while (!stack.isEmpty()) {
+      tag = (AbstractTag) stack.peek();
+      if (tag == WikipediaFilter.HTML_TABLE_OPEN) {
+        break;
+      }
+      stack.pop();
+      closeTag = (CloseTagToken) WikipediaFilter.CLOSE_TAGS.get(tag.getTagName());
+      buffer.append(closeTag.getCloseTag());
+      if (tag == WikipediaFilter.HTML_TR_OPEN || tag == WikipediaFilter.HTML_CAPTION_OPEN) {
+        break;
+      }
+    }
+  }
+
+  private void reduceTableCellStack(StringBuffer buffer, Stack stack) {
+    CloseTagToken closeTag;
+    AbstractTag tag;
+    while (!stack.isEmpty()) {
+      tag = (AbstractTag) stack.peek();
+      if (tag != WikipediaFilter.HTML_TH_OPEN && tag != WikipediaFilter.HTML_TD_OPEN) {
+        break;
+      }
+      stack.pop();
+      closeTag = (CloseTagToken) WikipediaFilter.CLOSE_TAGS.get(tag.getTagName());
+      buffer.append(closeTag.getCloseTag());
+      if (tag == WikipediaFilter.HTML_TR_OPEN || tag == WikipediaFilter.HTML_CAPTION_OPEN || tag == WikipediaFilter.HTML_TH_OPEN
+          || tag == WikipediaFilter.HTML_TD_OPEN) {
+        break;
+      }
+    }
+  }
+
+  //    // example
+  //// {| border=1
+  //// |Zelle 1
+  //// |
+  //// {| border=2
+  //// |Zelle A
+  //// |-
+  //// |Zelle B
+  //// |}
+  //// |Zelle 3
+  //// |}
+  //
+  //    int temp = fCurrentPosition;
+  //    // StringBuffer suffixBuffer = new StringBuffer();
+  //    Table table = new Table(fContext.getRenderContext());
+  //    // char currentChar = ' ';
+  //    char lastChar = ' ';
+  //    // int startPosition = 0;
+  //    // int currentPosition = 0;
+  //    StringBuffer buffer = new StringBuffer();
+  //    int thStartPosition = 0;
+  //
+  //    try { // read first line
+  //      fCurrentCharacter = fSource[fCurrentPosition++];
+  //      // TODO improve this for different table attributes
+  //      while (fCurrentCharacter != '\n' ) {
+  //        fCurrentCharacter = fSource[fCurrentPosition++];
+  //        // System.out.println(fCurrentCharacter);
+  //      }
+  //      table.newRow();
+  //      lastChar = fCurrentCharacter;
+  //      fCurrentCharacter = fSource[fCurrentPosition++];
+  //      while (true) {
+  //
+  //        switch (fCurrentCharacter) {
+  //          // case '{' : // start of nested table ?
+  //          // if (getNextChar('|') && handleWikipediaTable()) { // Wikipedia table
+  // end reached
+  //          // return true;
+  //          // }
+  //          // break;
+  //          case '!' :
+  //            if (lastChar == '\n') {
+  //              table.addCell(buffer.toString());
+  //              // System.out.println(buffer.toString());
+  //              buffer.setLength(0);
+  //              thStartPosition = fCurrentPosition;
+  //              while (true) {
+  //                lastChar = fCurrentCharacter;
+  //                fCurrentCharacter = fSource[fCurrentPosition++];
+  //                if (fCurrentCharacter == '|') {
+  //                  break;
+  //                }
+  //                if (fCurrentCharacter == '\n') {
+  //                  lastChar = '\n';
+  //                  fCurrentPosition = thStartPosition;
+  //                  break;
+  //                }
+  //              }
+  //            } else {
+  //              buffer.append(fCurrentCharacter);
+  //            }
+  //            break;
+  //          case '|' :
+  //            if (lastChar == '\n') {
+  //              if (getNextChar('}')) { // Wikipedia table end reached
+  //                table.addCell(buffer.toString());
+  //                StringWriter writer = new StringWriter();
+  //                try {
+  //                  table.appendTo(writer);
+  //                  fResultBuffer.append(writer.getBuffer());
+  //                } catch (IOException e1) {
+  //                  // TODO Auto-generated catch block
+  //                  e1.printStackTrace();
+  //                  return false;
+  //                }
+  //                return true;
+  //              } else if (getNextChar('-')) {
+  //                table.addCell(buffer.toString());
+  //                buffer.setLength(0);
+  //                table.newRow();
+  //                while (true) {
+  //                  lastChar = fCurrentCharacter;
+  //                  fCurrentCharacter = fSource[fCurrentPosition++];
+  //                  if (fCurrentCharacter == '|' || fCurrentCharacter == '!') {
+  //                    break;
+  //                  }
+  //                }
+  //               // continue;
+  //              } else {
+  //                if (buffer.length()>0) {
+  //                  table.addCell(buffer.toString());
+  //                  buffer.setLength(0);
+  //                }
+  //              }
+  //            } else if (getNextChar('|')) {
+  //              table.addCell(buffer.toString());
+  //              // System.out.println(buffer.toString());
+  //              buffer.setLength(0);
+  //            } else {
+  //              buffer.append(fCurrentCharacter);
+  //            }
+  //            break;
+  //          default :
+  //            buffer.append(fCurrentCharacter);
+  //        }
+  //        lastChar = fCurrentCharacter;
+  //        fCurrentCharacter = fSource[fCurrentPosition++];
+  //      }
+  //
+  //    } catch (IndexOutOfBoundsException e) {
+  //
+  //    }
+  //    fCurrentPosition = temp - 1;
+  //    return false;
+  //  }
+  private void handleWikipediaLink(String linkText, String suffix) {
+    String name = linkText;
+    if (name != null) {
+      int index = name.indexOf("http://");
+      // Configuration probably wrote [http://radeox.org] instead of
+      // http://radeox.org
+      if (index != -1) {
+        WikipediaFilter.createExternalLink(fResultBuffer, fWikiEngine, name.substring(index));
+        // show error
+        // fResult.append("<div class=\"error\">Do not surround URLs
+        // with [...].</div>");
+      } else {
+        // trim the name and unescape it
+        name = Encoder.unescape(name.trim());
+        //                Is there an alias like [alias|link] ?
+        int pipeIndex = name.indexOf('|');
+        String alias = "";
+        if (-1 != pipeIndex) {
+          alias = name.substring(pipeIndex + 1);
+          name = name.substring(0, pipeIndex);
+        }
+
+        int hashIndex = name.lastIndexOf('#');
+
+        String hash = "";
+        if (-1 != hashIndex && hashIndex != name.length() - 1) {
+          hash = name.substring(hashIndex + 1);
+          name = name.substring(0, hashIndex);
+        }
+
+        //                             int colonIndex = name.indexOf(':');
+        //                             // typed link ?
+        //                             if (-1 != colonIndex) {
+        //                                     // for now throw away the fType information
+        //                                     name = name.substring(colonIndex + 1);
+        //                             }
+
+        int atIndex = name.lastIndexOf('@');
+        // InterWiki link ?
+        if (-1 != atIndex) {
+          String extSpace = name.substring(atIndex + 1);
+          // known extarnal space ?
+          InterWiki interWiki = InterWiki.getInstance();
+          if (interWiki.contains(extSpace)) {
+            name = name.substring(0, atIndex);
+            Writer writer = new StringBufferWriter(fResultBuffer);
+            try {
+              if (-1 != hashIndex) {
+                interWiki.expand(writer, extSpace, name, hash);
+              } else {
+                interWiki.expand(writer, extSpace, name, "");
+              }
+            } catch (IOException e) {
+              //              log.debug("InterWiki " + extSpace + " not found.");
+            }
+          } else {
+            fResultBuffer.append("&#91;<span class=\"error\">");
+            fResultBuffer.append(name);
+            fResultBuffer.append("?</span>&#93;");
+          }
+        } else {
+          // internal link
+          if (name.startsWith("Image:") && (fWikiEngine instanceof ImageRenderEngine)) {
+            // server part of rendering images
+            ImageRenderEngine imageEngine = (ImageRenderEngine) fWikiEngine;
+            //                 fResultBuffer.append("<img src=\"space/1/2004-11-21/5/");
+            fResultBuffer.append("<img src=\"");
+            fResultBuffer.append(FilterUtil.createServerImage(null, name.substring(6), null));
+            fResultBuffer.append("\">");
+          } else if (fWikiEngine != null && fWikiEngine instanceof WikiRenderEngine) {
+            if (((WikiRenderEngine) fWikiEngine).exists(name)) {
+              String view = name + suffix;
+              if (-1 != pipeIndex) {
+                view = alias + suffix;
+              }
+              if (name.startsWith("Image:")) {
+                fResultBuffer.append("<img src=\"");
+
+                fResultBuffer.append(FilterUtil.createHTMLLink(null, name, null));
+                fResultBuffer.append("\">");
+              } else {
+                // Do not add hash if an alias was given
+                if (-1 != hashIndex) {
+                  ((WikiRenderEngine) fWikiEngine).appendLink(fResultBuffer, name, view, hash);
+                } else {
+                  ((WikiRenderEngine) fWikiEngine).appendLink(fResultBuffer, name, view);
+                }
+              }
+            } else if (((WikiRenderEngine) fWikiEngine).showCreate()) {
+              ((WikiRenderEngine) fWikiEngine).appendCreateLink(fResultBuffer, name, name + suffix);
+              // links with "create" are not cacheable because
+              // a missing wiki could be created
+              fContext.getRenderContext().setCacheable(false);
+            } else {
+              // cannot display/create wiki, so just display
+              // the text
+              fResultBuffer.append(name);
+            }
+          } else {
+            // cannot display/create wiki, so just display the text
+            fResultBuffer.append(name);
+          }
+        }
+      }
+    }
+  }
+
+  public String createAnchor(String head) {
+    StringBuffer result = new StringBuffer(head.length() + 1);
+    char ch;
+    result.append('a');
+    // reduce Anchorstring
+    for (int i = 0; i < head.length(); i++) {
+      ch = head.charAt(i);
+      if ('a' <= ch && 'z' >= ch) {
+        result.append(ch);
+      } else if ('A' <= ch && 'Z' >= ch) {
+        result.append(ch);
+      } else if ('0' <= ch && '9' >= ch) {
+        result.append(ch);
+      }
+      //        switch (ch) {
+      //          case ' ' :
+      //            result.append('_');
+      //            break;
+      //          case '<' : // special html escape character
+      //            fResult.append(Encoder.toEntity('<'));
+      //            break;
+      //          case '>' : // special html escape character
+      //            fResult.append(Encoder.toEntity('>'));
+      //            break;
+      //          case '&' : // special html escape character
+      //            fResult.append(Encoder.toEntity('&'));
+      //            break;
+      //          case '\'' : // special html escape character
+      //            fResult.append(Encoder.toEntity('\''));
+      //            break;
+      //          case '\"' : // special html escape character
+      //            fResult.append(Encoder.toEntity('\"'));
+      //            break;
+      //          default :
+      //            result.append(ch);
+      //        }
+    }
+    return result.toString();
+  }
+
+  public static StringBuffer appendLink(StringBuffer buffer, String name, String view, String target) {
+    return appendLinkWithRoot(buffer, null, name + "#" + target, view);
+  }
+
+  /**
+   * Create a link with a root and a special view. The name will not be url encoded!
+   */
+  public static StringBuffer appendLinkWithRoot(StringBuffer buffer, String root, String name, String view) {
+    buffer.append("<a href=\"");
+    if (root != null) {
+      buffer.append(root);
+      buffer.append("/");
+    }
+    buffer.append(name);
+    buffer.append("\">");
+    buffer.append(Encoder.escape(view));
+    buffer.append("</a>");
+    return buffer;
+  }
+
+  /**
+   * add an entry to the "table of content" TODO refactor this to a class
+   * 
+   * @param toc
+   * @param head
+   * @param anchor
+   * @param headLevel
+   */
+  private void addToTableOfContent(ArrayList toc, String head, String anchor, int headLevel) {
+    int level = 1;
+    if (level == headLevel) {
+      String snipName = "";
+      //      if (fSnip != null) {
+      //        snipName = fSnip.getName();
+      //      }
+
+      StringBuffer link = new StringBuffer(snipName.length() + 40 + head.length() + anchor.length());
+      link.append("<li>");
+      //TODO create link for table of content
+      appendLink(link, snipName, head, anchor);
+      link.append("</li>");
+      toc.add(link.toString());
+    } else {
+      if (toc.size() > 0) {
+        if (toc.get(toc.size() - 1) instanceof ArrayList) {
+          addToTableOfContent((ArrayList) toc.get(toc.size() - 1), head, anchor, --headLevel);
+          return;
+        }
+      }
+      ArrayList list = new ArrayList();
+      toc.add(list);
+      addToTableOfContent(list, head, anchor, --headLevel);
+    }
+  }
+
+  /**
+   * handle head for table of content
+   * 
+   * @param head
+   * @param headLevel
+   */
+  private void handleHead(String head, int headLevel) {
+    if (head != null) {
+      String anchor = createAnchor(head.trim());
+
+      if (fTableOfContent == null) {
+        // create new table of content
+        fTableOfContent = new ArrayList();
+        // copy fResult and new initialization:
+
+        fResultBufferHeader = fResultBuffer;
+        fResultBuffer = new StringBuffer(fResultBuffer.capacity());
+      }
+      addToTableOfContent(fTableOfContent, head, anchor, headLevel);
+
+      fResultBuffer.append("<h");
+      fResultBuffer.append(headLevel);
+      fResultBuffer.append("><a name=\"");
+      fResultBuffer.append(anchor);
+      fResultBuffer.append("\">");
+      fResultBuffer.append(head);
+      fResultBuffer.append("</a></h");
+      fResultBuffer.append(headLevel);
+      fResultBuffer.append(">");
+      //      if (headLevel <= 2) {
+      //        fResultBuffer.append("<hr/>");
+      //      }
+    }
+  }
+
+  private boolean getList(char listChar, String openTag, String closeTag) {
+    int currentPosition = fCurrentPosition;
+    int level = getNumberOfChar(listChar) + 1;
+    if (getNextChar('.') && getNextChar(' ')) {
+      int tempPosition = checkWhitespaces(fWhiteStartPosition, fCurrentPosition - 3 - level);
+      if (tempPosition >= 0) {
+        copyWhite(fWhiteStart, fWhiteStartPosition, 2 + level);
+        fWhiteStart = false;
+        AbstractTag tok = (AbstractTag) fTokenStack.peek();
+        if (tok instanceof ListToken) {
+          ListToken listToken = (ListToken) tok;
+          int topLevel = listToken.getLevel();
+          if (listToken.getToken() == WikipediaFilter.TokenLIST_OL_START) {
+            if (level > topLevel) {
+              fTokenStack.push(new ListToken(WikipediaFilter.TokenLIST_OL_START, topLevel + 1));
+              fResultBuffer.append(openTag + "<li>");
+            } else if (level < topLevel) {
+              fTokenStack.pop();
+              fResultBuffer.append("</li>" + closeTag + "</li><li>");
+            } else {
+              fResultBuffer.append("</li><li>");
+            }
+          } else {
+            fTokenStack.push(new ListToken(WikipediaFilter.TokenLIST_OL_START, level));
+            fResultBuffer.append(openTag + "<li>");
+          }
+        } else {
+          fTokenStack.push(new ListToken(WikipediaFilter.TokenLIST_OL_START, 1));
+          fResultBuffer.append("\n" + openTag + "<li>");
+        }
+        return true;
+      }
+    }
+    fCurrentPosition = currentPosition;
+    return false;
+  }
+
+  /**
+   * read until the string is found
+   * 
+   * @param name
+   * @return
+   */
+  private final boolean readUntilString(String testedString) {
+    int temp = fCurrentPosition;
+    int index = fStringSource.indexOf(testedString, fCurrentPosition);
+    if (index != (-1)) {
+      fCurrentPosition = index + testedString.length();
+      return true;
+    }
+    return false;
+  }
+
+  /**
+   * read until character is found
+   * 
+   * @param name
+   * @return
+   */
+  private final boolean readUntilChar(char testedChar) {
+    int temp = fCurrentPosition;
+    try {
+      while ((fCurrentCharacter = fSource[fCurrentPosition++]) != testedChar) {
+      }
+      return true;
+    } catch (IndexOutOfBoundsException e) {
+      fCurrentPosition = temp;
+      return false;
+    }
+  }
+
+  /**
+   * read until character is found or end-of-line is reached
+   * 
+   * @param name
+   * @return -1 - for IndexOutOfBoundsException; 0 - for LF found; 1 - for testedChar found
+   */
+  private final int readUntilCharOrEOL(char testedChar) {
+    int temp = fCurrentPosition;
+    try {
+      while ((fCurrentCharacter = fSource[fCurrentPosition++]) != testedChar) {
+        //                             if (fCurrentCharacter == '\n') {
+        //                                     return 0;
+        //                             }
+      }
+      return 1;
+    } catch (IndexOutOfBoundsException e) {
+      fCurrentPosition = temp;
+      return -1;
+    }
+  }
+
+  /**
+   * read until character is found or end-of-line is reached
+   * 
+   * @param name
+   * @return -1 - for IndexOutOfBoundsException; 0 - for LF found; 1 - for testedChar found
+   */
+  private final boolean readUntilEOL() {
+    int temp = fCurrentPosition;
+    try {
+      while (true) {
+        fCurrentCharacter = fSource[fCurrentPosition++];
+        if (fCurrentCharacter == '\n' || fCurrentCharacter == '\r') {
+          return true;
+        }
+      }
+    } catch (IndexOutOfBoundsException e) {
+      --fCurrentPosition;
+      return true;
+    }
+  }
+
+  /**
+   * Returns the view of the wiki name that is shown to the fUser. Overwrite to support other views for example transform
+   * "WikiLinking" to "Wiki Linking". Does nothing by default.
+   * 
+   * @return view The view of the wiki name
+   */
+  //  protected String getWikiView(String name) {
+  //    return name;
+  //  }
+  private void handleMacro(String completeMacroSubString, String command, String unsplittedMacroParameters, String group3) {
+    if (command != null) {
+      // {$peng} are variables not macros.
+      if (!command.startsWith("$")) {
+        MacroParameter mParams = fContext.getMacroParameter();
+
+        if (group3 != null) {
+          mParams.setContent(group3);
+          mParams.setContentStart(0);
+          mParams.setContentEnd(group3.length());
+        }
+        if (unsplittedMacroParameters != null && unsplittedMacroParameters.length() > 1) {
+          //            mParams.setParams(parseParameters(unsplittedMacroParameters));
+          mParams.setParams(unsplittedMacroParameters);
+        }
+        mParams.setStart(0);
+        mParams.setEnd(completeMacroSubString.length());
+
+        // @DANGER: recursive calls may replace macros in included
+        // source code
+        try {
+          if (fMacros.containsKey(command)) {
+            Macro macro = (Macro) fMacros.get(command);
+
+            // recursively filter macros within macros
+            if (null != mParams.getContent() && !(macro instanceof INoParserBodyFilterMacro)) {
+              mParams.setContent(WikipediaFilter.filterParser(mParams.getContent(), fContext, fMacros, fRecursionLevel));
+            }
+            StringBufferWriter writer = new StringBufferWriter(new StringBuffer(256));
+            macro.execute(writer, mParams);
+            StringBuffer buffer = writer.getBuffer();
+            if (macro instanceof IRenderResultMacro) {
+              fResultBuffer.append(WikipediaFilter.filterParser(buffer.toString(), fContext, fMacros, fRecursionLevel));
+            } else {
+              fResultBuffer.append(buffer);
+            }
+
+          } else if (command.startsWith("!")) {
+
+            RenderEngine engine = fContext.getRenderContext().getRenderEngine();
+            if (engine instanceof IncludeRenderEngine) {
+              String include = ((IncludeRenderEngine) engine).include(command.substring(1));
+              if (null != include) {
+                // Filter paramFilter = new
+                // ParamFilter(mParams);
+                // included = paramFilter.filter(included,
+                // null);
+                //                  fResult.append(include);
+
+                fResultBuffer.append(WikipediaFilter.filterParser(include, fContext, fMacros, fRecursionLevel));
+
+              } else {
+                fResultBuffer.append(command.substring(1) + " not found.");
+              }
+            }
+
+            return;
+          } else {
+            //              fResult.append(group0);
+            copyWhite(completeMacroSubString);
+            return;
+          }
+        } catch (IllegalArgumentException e) {
+
+          fResultBuffer.append("<div class=\"error\">" + command + ": " + e.getMessage() + "</div>");
+
+          e.printStackTrace();
+
+        } catch (Throwable e) {
+          //          log.warn("MacroFilter: unable to format macro: " + command, e);
+          fResultBuffer.append("<div class=\"error\">" + command + ": " + e.getMessage() + "</div>");
+          e.printStackTrace();
+          return;
+        }
+      } else {
+        fResultBuffer.append("<");
+        fResultBuffer.append(command.substring(1));
+        fResultBuffer.append(">");
+      }
+    } else {
+      //        fResult.append(group0);
+      copyWhite(completeMacroSubString);
+    }
+  }
+
+  public void parse() {
+    int token = WikipediaFilter.TokenSTART;
+    fTokenStack.add(WikipediaFilter.START);
+    //    fListStack.add(START);
+    try {
+      while ((token = getNextToken()) != WikipediaFilter.TokenEOF) {
+        switch (token) {
+        case WikipediaFilter.TokenBOLD:
+          if (fTokenStack.peek() == WikipediaFilter.BOLD) {
+            fTokenStack.pop();
+            fResultBuffer.append("</b>");
+          } else {
+            fTokenStack.push(WikipediaFilter.BOLD);
+            fResultBuffer.append("<b>");
+          }
+          break;
+        case WikipediaFilter.TokenITALIC:
+          if (fTokenStack.peek() == WikipediaFilter.ITALIC) {
+            fTokenStack.pop();
+            fResultBuffer.append("</i>");
+          } else {
+            fTokenStack.push(WikipediaFilter.ITALIC);
+            fResultBuffer.append("<i>");
+          }
+          break;
+        case WikipediaFilter.TokenSTRONG:
+          if (fTokenStack.peek() == WikipediaFilter.STRONG) {
+            fTokenStack.pop();
+            fResultBuffer.append("</strong>");
+          } else {
+            fTokenStack.push(WikipediaFilter.STRONG);
+            fResultBuffer.append("<strong>");
+          }
+          break;
+        case WikipediaFilter.TokenEM:
+          if (fTokenStack.peek() == WikipediaFilter.EM) {
+            fTokenStack.pop();
+            fResultBuffer.append("</em>");
+          } else {
+            fTokenStack.push(WikipediaFilter.EM);
+            fResultBuffer.append("<em>");
+          }
+          break;
+        case WikipediaFilter.TokenSTRIKETHROUGH:
+          if (fTokenStack.peek() == WikipediaFilter.STRIKETHROUGH) {
+            fTokenStack.pop();
+            fResultBuffer.append("</strike>");
+          } else {
+            fTokenStack.push(WikipediaFilter.STRIKETHROUGH);
+            fResultBuffer.append("<strike>");
+          }
+          break;
+        //            case TokenLIST_UL_START :
+        //              if (fTokenStack.peek().equals(LIST_UL_START)) {
+        //                fResult.append("</li>\n<li>");
+        //              } else {
+        //                fTokenStack.push(LIST_UL_START);
+        //                fResult.append("\n<ul class=\"star\">\n<li>");
+        //              }
+        //              break;
+        //            case TokenLIST_UL_END :
+        //              fTokenStack.pop();
+        //              fResult.append("</li>\n</ul>\n");
+        //              break;
+        //            case TokenLIST_OL_START :
+        //              if (fTokenStack.peek().equals(LIST_OL_START)) {
+        //                fResult.append("</li>\n<li>");
+        //              } else {
+        //                fTokenStack.push(LIST_OL_START);
+        //                fResult.append("\n<ol>\n<li>");
+        //              }
+        //              break;
+        //            case TokenLIST_OL_END :
+        //              fTokenStack.pop();
+        //              fResult.append("</li>\n</ol>\n");
+        //              break;
+        }
+      }
+    } catch (InvalidInputException e) {
+      //
+    }
+    // clear rest of stack if necessary (case of error in syntax!?)
+    AbstractTag tok;
+    while ((tok = (AbstractTag) fTokenStack.pop()) != WikipediaFilter.START) {
+      if (tok instanceof OpenTagToken) {
+
+        CloseTagToken closeToken = (CloseTagToken) WikipediaFilter.CLOSE_TAGS.get(tok.getTagName());
+        if (closeToken == null) {
+          // here is something wrong ???
+          fResultBuffer.append("</" + (tok.getTagName()) + ">");
+        } else {
+          fResultBuffer.append(closeToken.getCloseTag());
+        }
+      } else if (tok == WikipediaFilter.BOLD) {
+        fResultBuffer.append("</b>");
+      } else if (tok == WikipediaFilter.ITALIC) {
+        fResultBuffer.append("</i>");
+      } else if (tok == WikipediaFilter.STRONG) {
+        fResultBuffer.append("</strong>");
+      } else if (tok == WikipediaFilter.EM) {
+        fResultBuffer.append("</em>");
+      } else if (tok == WikipediaFilter.STRIKETHROUGH) {
+        fResultBuffer.append("</strike>");
+      } else if (tok.equals(WikipediaFilter.LIST_UL_START)) {
+        fResultBuffer.append("</li>\n</ul>\n");
+      } else if (tok.equals(WikipediaFilter.LIST_OL_START)) {
+        fResultBuffer.append("</li>\n</ol>\n");
+      }
+    }
+
+    if (fResultBufferHeader != null) {
+      int tocStart = fResultBufferHeader.length();
+      fResultBufferHeader.append("<table id=\"toc\" border=\"0\"><tr><th>Table of contents</th></tr><tr><td>");
+      fResultBufferHeader.append("<ol>");
+      createToC(fTableOfContent);
+      fResultBufferHeader.append("</ol>");
+      fResultBufferHeader.append("</td></tr></table><hr/>");
+
+      fResultBufferHeader.append(fResultBuffer);
+      fResultBuffer = fResultBufferHeader;
+      fResultBufferHeader = null;
+      fTableOfContent = null;
+    }
+  }
+
+  private void createToC(ArrayList toc) {
+    if (toc.size() == 1 && (toc.get(0) instanceof ArrayList)) {
+      createToC((ArrayList) toc.get(0));
+      return;
+    }
+    for (int i = 0; i < toc.size(); i++) {
+      if (toc.get(i) instanceof ArrayList) {
+        fResultBufferHeader.append("<ol>");
+        createToC((ArrayList) toc.get(i));
+        fResultBufferHeader.append("</ol>");
+      } else {
+        fResultBufferHeader.append(toc.get(i));
+      }
+    }
+  }
+
+  //  public int readUntil(String testString) throws InvalidInputException {
+  //    startPosition = currentPosition;
+  //    int tempPosition;
+  //    boolean flag;
+  //    try {
+  //      while (true) {
+  //        currentCharacter = source[currentPosition++];
+  //        if (currentCharacter == testString.charAt(0)) {
+  //          tempPosition = currentPosition;
+  //          flag = true;
+  //          for (int i = 1; i < testString.length(); i++) {
+  //            currentCharacter = source[currentPosition++];
+  //            if (currentCharacter != testString.charAt(i)) {
+  //              flag = false;
+  //              currentPosition = tempPosition;
+  //              break;
+  //            }
+  //          }
+  //          if (flag) {
+  //            return TokenBODY;
+  //          }
+  //        }
+  //      }
+  //    } catch (IndexOutOfBoundsException e) {
+  //      // end of scanner text
+  //    }
+  //    return TokenEOF;
+  //  }
+
+  public int scanIdentifierOrKeyword(boolean isVariable) throws InvalidInputException {
+    while (getNextCharAsWikiPluginIdentifierPart()) {
+    }
+    ;
+    return WikipediaFilter.TokenIdentifier;
+  }
+
+  private final void setSource(char[] source) {
+    //the source-buffer is set to sourceString
+    if (source == null) {
+      this.fSource = new char[0];
+    } else {
+      this.fSource = source;
+    }
+    //      this.fEOFPosition = this.fSource.length;
+    //      fStartPosition = -1;
+  }
+
+  private void unexpectedTag(String tag) {
+    fResultBuffer.append("<div class=\"error\">Unexpected end for tag: &lt;" + tag + "&gt;</div>");
+  }
+
+  /**
+   * @return Returns the context.
+   */
+  public FilterContext getContext() {
+    return fContext;
+  }
+
+  /**
+   * @param context
+   *          The context to set.
+   */
+  public void setContext(FilterContext context) {
+    fContext = context;
+  }
+
+  /**
+   * @return Returns the wikiEngine.
+   */
+  public RenderEngine getWikiEngine() {
+    return fWikiEngine;
+  }
+
+  /**
+   * @param wikiEngine
+   *          The wikiEngine to set.
+   */
+  public void setWikiEngine(RenderEngine wikiEngine) {
+    fWikiEngine = wikiEngine;
+  }
+}
\ No newline at end of file
diff --git a/archive/org.plog4u.wiki/src/org/plog4u/wiki/macro/CodeMacro.java b/archive/org.plog4u.wiki/src/org/plog4u/wiki/macro/CodeMacro.java
new file mode 100644 (file)
index 0000000..50a9889
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ * This file is part of "SnipSnap Radeox Rendering Engine".
+ * 
+ * Copyright (c) 2002 Stephan J. Schmidt, Matthias L. Jugel All Rights Reserved.
+ * 
+ * Please visit http://radeox.org/ for updates and contact.
+ * 
+ * --LICENSE NOTICE-- This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser
+ * General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any
+ * later version.
+ * 
+ * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA --LICENSE NOTICE--
+ */
+
+package org.plog4u.wiki.macro;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Locale;
+import java.util.Map;
+import java.util.ResourceBundle;
+
+
+//import org.apache.commons.logging.Log;
+//import org.apache.commons.logging.LogFactory;
+import org.plog4u.wiki.filter.ICachableMacro;
+import org.plog4u.wiki.filter.INoParserBodyFilterMacro;
+import org.plog4u.wiki.macro.code.AbstractCPPBasedCodeFilter;
+import org.radeox.api.engine.context.InitialRenderContext;
+import org.radeox.api.engine.context.RenderContext;
+import org.radeox.filter.context.BaseFilterContext;
+import org.radeox.filter.context.FilterContext;
+import org.radeox.macro.LocalePreserved;
+import org.radeox.macro.code.SourceCodeFormatter;
+import org.radeox.macro.parameter.MacroParameter;
+import org.radeox.util.Encoder;
+import org.radeox.util.Service;
+/*
+ * Macro for displaying programming language source code. CodeMacro knows about different source code formatters which can be
+ * plugged into radeox to display more languages. CodeMacro displays Java, Ruby or SQL code.
+ * 
+ * @author stephan @team sonicteam
+ * 
+ */
+
+public class CodeMacro extends LocalePreserved implements INoParserBodyFilterMacro, ICachableMacro {
+//  private static Log log = LogFactory.getLog(CodeMacro.class);
+
+  private Map formatters;
+  private FilterContext nullContext = new BaseFilterContext();
+
+  private String start;
+  private String end;
+
+  private String[] paramDescription = { "?1: syntax highlighter to use, defaults to java" };
+
+  public String[] getParamDescription() {
+    return paramDescription;
+  }
+
+  public String getLocaleKey() {
+    return "macro.code";
+  }
+
+  public void setInitialContext(InitialRenderContext context) {
+    super.setInitialContext(context);
+    Locale outputLocale = (Locale) context.get(RenderContext.OUTPUT_LOCALE);
+    String outputName = (String) context.get(RenderContext.OUTPUT_BUNDLE_NAME);
+    ResourceBundle outputMessages = ResourceBundle.getBundle(outputName, outputLocale);
+
+    start = outputMessages.getString(getLocaleKey() + ".start");
+    end = outputMessages.getString(getLocaleKey() + ".end");
+  }
+
+  public CodeMacro() {
+    formatters = new HashMap();
+
+    Iterator formatterIt = Service.providers(SourceCodeFormatter.class);
+    while (formatterIt.hasNext()) {
+      try {
+        SourceCodeFormatter formatter = (SourceCodeFormatter) formatterIt.next();
+        String name = formatter.getName();
+        if (formatters.containsKey(name)) {
+          SourceCodeFormatter existing = (SourceCodeFormatter) formatters.get(name);
+          if (existing.getPriority() < formatter.getPriority()) {
+            formatters.put(name, formatter);
+//            log.debug("Replacing formatter: " + formatter.getClass() + " (" + name + ")");
+          }
+        } else {
+          formatters.put(name, formatter);
+//          log.debug("Loaded formatter: " + formatter.getClass() + " (" + name + ")");
+        }
+      } catch (Exception e) {
+//        log.warn("CodeMacro: unable to load code formatter", e);
+      }
+    }
+
+    addSpecial('[');
+    addSpecial(']');
+    addSpecial('{');
+    addSpecial('}');
+    addSpecial('*');
+    addSpecial('-');
+    addSpecial('\\');
+  }
+
+  public void execute(Writer writer, MacroParameter params) throws IllegalArgumentException, IOException {
+
+    SourceCodeFormatter formatter = null;
+    String result;
+    if (params.getLength() == 0 || !formatters.containsKey(params.get("0"))) {
+      formatter = (SourceCodeFormatter) formatters.get(initialContext.get(RenderContext.DEFAULT_FORMATTER));
+      if (null == formatter) {
+        System.err.println("Formatter not found.");
+        formatter = (SourceCodeFormatter) formatters.get("java");
+        result = formatter.filter(params.getContent(), nullContext);
+      } else if (formatter instanceof AbstractCPPBasedCodeFilter) {
+        result = formatter.filter(params.getContent(), nullContext);
+      } else {
+        result = formatter.filter(Encoder.escape(params.getContent()), nullContext);
+      }
+    } else {
+      formatter = (SourceCodeFormatter) formatters.get(params.get("0"));
+      if (formatter instanceof AbstractCPPBasedCodeFilter) {
+        result = formatter.filter(params.getContent(), nullContext);
+      } else {
+        result = formatter.filter(Encoder.escape(params.getContent()), nullContext);
+      }
+    }
+
+    writer.write(start);
+    writer.write(replace(result.trim()));
+    writer.write(end);
+    return;
+  }
+}
diff --git a/archive/org.plog4u.wiki/src/org/plog4u/wiki/macro/HMathMacro.java b/archive/org.plog4u.wiki/src/org/plog4u/wiki/macro/HMathMacro.java
new file mode 100644 (file)
index 0000000..daa5e2a
--- /dev/null
@@ -0,0 +1,9 @@
+package org.plog4u.wiki.macro;
+
+
+import org.plog4u.wiki.filter.INoParserBodyFilterMacro;
+import org.radeox.macro.BaseMacro;
+public abstract class HMathMacro extends BaseMacro implements INoParserBodyFilterMacro {
+
+}
diff --git a/archive/org.plog4u.wiki/src/org/plog4u/wiki/macro/LinkMacro.java b/archive/org.plog4u.wiki/src/org/plog4u/wiki/macro/LinkMacro.java
new file mode 100644 (file)
index 0000000..e3e08c0
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * This file is part of "SnipSnap Radeox Rendering Engine".
+ *
+ * Copyright (c) 2002 Stephan J. Schmidt, Matthias L. Jugel
+ * All Rights Reserved.
+ *
+ * Please visit http://radeox.org/ for updates and contact.
+ *
+ * --LICENSE NOTICE--
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * --LICENSE NOTICE--
+ */
+package org.plog4u.wiki.macro;
+
+import java.io.IOException;
+import java.io.Writer;
+
+
+import org.plog4u.wiki.filter.ICachableMacro;
+import org.radeox.api.engine.ImageRenderEngine;
+import org.radeox.api.engine.RenderEngine;
+import org.radeox.api.engine.context.RenderContext;
+import org.radeox.macro.BaseLocaleMacro;
+import org.radeox.macro.parameter.MacroParameter;
+import org.radeox.util.Encoder;
+
+/*
+ * Macro for displaying external links with a name. The normal UrlFilter
+ * takes the url as a name.
+ *
+ * @author stephan
+ * @team sonicteam
+ */
+
+public class LinkMacro extends BaseLocaleMacro implements ICachableMacro {
+  public String getLocaleKey() {
+    return "macro.link";
+  }
+
+  public void execute(Writer writer, MacroParameter params)
+      throws IllegalArgumentException, IOException {
+
+    RenderContext context = params.getContext();
+    RenderEngine engine = context.getRenderEngine();
+
+    String text = params.get("text", 0);
+    String url = params.get("url", 1);
+    String img = params.get("img", 2);
+
+    // check for single url argument (text == url)
+    if(params.getLength() == 1) {
+      url = text;
+      text = Encoder.toEntity(text.charAt(0)) + Encoder.escape(text.substring(1));
+    }
+
+    if (url != null && text != null) {
+      writer.write("<span class=\"nobr\">");
+      if (!"none".equals(img) && engine instanceof ImageRenderEngine) {
+        writer.write(((ImageRenderEngine) engine).getExternalImageLink());
+      }
+      writer.write("<a href=\"");
+      writer.write(Encoder.escape(url));
+      writer.write("\">");
+      writer.write(text);
+      writer.write("</a></span>");
+    } else {
+      throw new IllegalArgumentException("link needs a name and a url as argument");
+    }
+    return;
+  }
+}
diff --git a/archive/org.plog4u.wiki/src/org/plog4u/wiki/macro/MacroListMacro.java b/archive/org.plog4u.wiki/src/org/plog4u/wiki/macro/MacroListMacro.java
new file mode 100644 (file)
index 0000000..593b9e2
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * This file is part of "SnipSnap Radeox Rendering Engine".
+ * 
+ * Copyright (c) 2002 Stephan J. Schmidt, Matthias L. Jugel All Rights Reserved.
+ * 
+ * Please visit http://radeox.org/ for updates and contact.
+ * 
+ * --LICENSE NOTICE-- This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser
+ * General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any
+ * later version.
+ * 
+ * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA --LICENSE NOTICE--
+ */
+package org.plog4u.wiki.macro;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+
+import org.plog4u.wiki.filter.ICachableMacro;
+import org.plog4u.wiki.filter.IRenderResultMacro;
+import org.radeox.macro.BaseLocaleMacro;
+import org.radeox.macro.Macro;
+import org.radeox.macro.MacroRepository;
+import org.radeox.macro.parameter.MacroParameter;
+
+/*
+ * MacroListMacro displays a list of all known macros of the EngineManager with their name, parameters and a description.
+ * 
+ * @author Matthias L. Jugel
+ * 
+ */
+
+public class MacroListMacro extends BaseLocaleMacro implements IRenderResultMacro, ICachableMacro {
+  public String getLocaleKey() {
+    return "macro.macrolist";
+  }
+
+  public void execute(Writer writer, MacroParameter params) throws IllegalArgumentException, IOException {
+    if (params.getLength() == 0) {
+      appendTo(writer);
+    } else {
+      throw new IllegalArgumentException("MacroListMacro: number of arguments does not match");
+    }
+  }
+
+  public Writer appendTo(Writer writer) throws IOException {
+    List macroList = MacroRepository.getInstance().getPlugins();
+    Collections.sort(macroList);
+    Iterator iterator = macroList.iterator();
+    writer.write("{table}\n");
+    writer.write("Macro|Description|Parameters\n");
+    while (iterator.hasNext()) {
+      Macro macro = (Macro) iterator.next();
+      writer.write(macro.getName());
+      writer.write("|");
+      writer.write(macro.getDescription());
+      writer.write("|");
+      String[] params = macro.getParamDescription();
+      if (params.length == 0) {
+        writer.write("none");
+      } else {
+        for (int i = 0; i < params.length; i++) {
+          String description = params[i];
+          if (description.startsWith("?")) {
+            writer.write(description.substring(1));
+            writer.write(" (optional)");
+          } else {
+            writer.write(params[i]);
+          }
+          writer.write("\\\\");
+        }
+      }
+      writer.write("\n");
+    }
+    writer.write("{table}");
+    return writer;
+  }
+
+}
diff --git a/archive/org.plog4u.wiki/src/org/plog4u/wiki/macro/QuoteMacro.java b/archive/org.plog4u.wiki/src/org/plog4u/wiki/macro/QuoteMacro.java
new file mode 100644 (file)
index 0000000..4d3158d
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * This file is part of "SnipSnap Radeox Rendering Engine".
+ *
+ * Copyright (c) 2002 Stephan J. Schmidt, Matthias L. Jugel
+ * All Rights Reserved.
+ *
+ * Please visit http://radeox.org/ for updates and contact.
+ *
+ * --LICENSE NOTICE--
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * --LICENSE NOTICE--
+ */
+
+package org.plog4u.wiki.macro;
+
+import java.io.IOException;
+import java.io.Writer;
+
+
+//import org.apache.commons.logging.Log;
+//import org.apache.commons.logging.LogFactory;
+import org.plog4u.wiki.filter.ICachableMacro;
+import org.plog4u.wiki.filter.INoParserBodyFilterMacro;
+import org.radeox.macro.LocalePreserved;
+import org.radeox.macro.parameter.MacroParameter;
+
+/*
+ * Macro to display quotations from other sources. The
+ * output is wrapped usually in <blockquote> to look like
+ * a quotation.
+ *
+ * @author stephan
+ * @team sonicteam
+ */
+
+public class QuoteMacro extends LocalePreserved implements INoParserBodyFilterMacro, ICachableMacro {
+//  private static Log log = LogFactory.getLog(QuoteMacro.class);
+
+  private String[] paramDescription =
+      {"?1: source",
+       "?2: displayed description, default is Source"};
+
+  public String[] getParamDescription() {
+    return paramDescription;
+  }
+
+  public QuoteMacro() {
+  }
+
+  public String getLocaleKey() {
+    return "macro.quote";
+  }
+  public void execute(Writer writer, MacroParameter params)
+      throws IllegalArgumentException, IOException {
+
+    writer.write("<blockquote>");
+    writer.write(params.getContent());
+    String source = "Source"; // i18n
+    if (params.getLength() == 2) {
+      source = params.get(1);
+    }
+    // if more than one was present, we
+    // should show a description for the link
+    if (params.getLength() > 0) {
+      writer.write("<a href=\""+params.get(0)+"\">");
+      writer.write(source);
+      writer.write("</a>");
+    }
+    writer.write("</blockquote>");
+    return;
+  }
+}
diff --git a/archive/org.plog4u.wiki/src/org/plog4u/wiki/macro/code/AbstractCPPBasedCodeFilter.java b/archive/org.plog4u.wiki/src/org/plog4u/wiki/macro/code/AbstractCPPBasedCodeFilter.java
new file mode 100644 (file)
index 0000000..ec1de4d
--- /dev/null
@@ -0,0 +1,216 @@
+/*
+ * 
+ * Please visit http://radeox.org/ for updates and contact.
+ * 
+ * --LICENSE NOTICE-- This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser
+ * General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any
+ * later version.
+ * 
+ * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA --LICENSE NOTICE--
+ */
+
+package org.plog4u.wiki.macro.code;
+
+import java.util.HashMap;
+import java.util.HashSet;
+
+import org.radeox.filter.context.FilterContext;
+import org.radeox.macro.code.SourceCodeFormatter;
+
+/*
+ * Abstract C++ syntax based code filter
+ *  
+ */
+
+abstract public class AbstractCPPBasedCodeFilter implements SourceCodeFormatter {
+
+  public static void appendChar(StringBuffer result, char currentChar) {
+    switch (currentChar) {
+      case '\"' : // special html escape character
+        result.append("&#34;");
+        break;
+      case '<' : // special html escape character
+        result.append("&#60;");
+        break;
+      case '>' : // special html escape character
+        result.append("&#62;");
+        break;
+      case '&' : // special html escape character
+        result.append("&#38;");
+        break;
+      case '\'' : // special html escape character
+        result.append("&#39;");
+        break;
+      default :
+        result.append(currentChar);
+    }
+  }
+  public static void createHashMap(HashMap map, String str) {
+    map.put(str, "<b><font color=\"#750055\">"+str+"</font></b>");
+  }
+
+  public AbstractCPPBasedCodeFilter() {
+  }
+
+  private int appendIdentifier(
+    String input,
+    int identStart,
+    int currentPosition,
+    HashMap keywords,
+    HashSet objectWords,
+    StringBuffer result) {
+    String originalIdent = input.substring(identStart, --currentPosition);
+    String keywordIdent = originalIdent;
+    if (!isKeywordLowerCase()) {
+      keywordIdent = keywordIdent.toLowerCase();
+    }
+    String keywordValue = (String) keywords.get(keywordIdent);
+    if (keywordValue!=null) { 
+      result.append(keywordValue);
+//    } else if (objectWords != null && objectWords.contains(originalIdent)) {
+//      result.append("<font color=\"#7F9FBF\">");
+//      result.append(originalIdent);
+//      result.append("</font>");
+    } else {
+      result.append(originalIdent);
+    }
+    return currentPosition;
+  }
+
+  public String filter(String input, FilterContext context) {
+    char[] source = input.toCharArray();
+    int currentPosition = 0;
+    int identStart = 0;
+    char currentChar = ' ';
+
+    HashMap keywordsSet = getKeywordSet();
+    HashSet objectsSet = getObjectSet();
+    StringBuffer result = new StringBuffer(input.length() + input.length() / 4);
+    boolean identFound = false;
+    result.append("<font color=\"#000000\">");
+    try {
+      while (true) {
+        currentChar = source[currentPosition++];
+        //        if (currentChar >= 'a' && currentChar <= 'z' && isKeywordLowerCase()) {
+        //          identStart = currentPosition - 1;
+        //          identFound = true;
+        //          // start of identifier ?
+        //          while (currentChar >= 'a' && currentChar <= 'z') {
+        //            currentChar = source[currentPosition++];
+        //          }
+        //          currentPosition = appendIdentifier(input, identStart, currentPosition, keywordsSet, objectsSet, result);
+        //          identFound = false;
+        //          continue; // while loop
+        //        } else
+        if ((currentChar >= 'A' && currentChar <= 'Z') || (currentChar == '_') || (currentChar >= 'a' && currentChar <= 'z')) {
+          identStart = currentPosition - 1;
+          identFound = true;
+          // start of identifier ?
+          while ((currentChar >= 'a' && currentChar <= 'z') || (currentChar >= 'A' && currentChar <= 'Z') || currentChar == '_') {
+            currentChar = source[currentPosition++];
+          }
+          currentPosition = appendIdentifier(input, identStart, currentPosition, keywordsSet, objectsSet, result);
+          identFound = false;
+          continue; // while loop
+        } else if (currentChar == '\"') { //strings
+          result.append("<font color=\"#2A00FF\">");
+          appendChar(result, currentChar);
+          while (currentPosition < input.length()) {
+            currentChar = source[currentPosition++];
+            appendChar(result, currentChar);
+            if (currentChar == '\"' && source[currentPosition - 2] != '\\') {
+              break;
+            }
+          }
+          result.append("</font>");
+          continue;
+        } else if (currentChar == '/' && currentPosition < input.length() && source[currentPosition] == '/') {
+          // line comment
+          result.append("<font color=\"#3F7F5F\">");
+          appendChar(result, currentChar);
+          appendChar(result, source[currentPosition++]);
+          while (currentPosition < input.length()) {
+            currentChar = source[currentPosition++];
+            appendChar(result, currentChar);
+            if (currentChar == '\n') {
+              break;
+            }
+          }
+          result.append("</font>");
+          continue;
+        } else if (currentChar == '/' && currentPosition < input.length() && source[currentPosition] == '*') {
+          if (currentPosition < (input.length() - 1) && source[currentPosition + 1] == '*') {
+            // javadoc style
+            result.append("<font color=\"#3F5FBF\">");
+          } else {
+            // multiline comment
+            result.append("<font color=\"#3F7F5F\">");
+          }
+          appendChar(result, currentChar);
+          appendChar(result, source[currentPosition++]);
+          while (currentPosition < input.length()) {
+            currentChar = source[currentPosition++];
+            appendChar(result, currentChar);
+            if (currentChar == '/' && source[currentPosition - 2] == '*') {
+              break;
+            }
+          }
+          result.append("</font>");
+          continue;
+        } else if (currentChar == '<' && isPHPTag() && currentPosition+3 < input.length() && source[currentPosition] == '?'
+            && source[currentPosition+1] == 'p'
+            && source[currentPosition+2] == 'h'
+            && source[currentPosition+3] == 'p') {
+          // php start tag
+          currentPosition++;
+          result.append("<font color=\"#7F0000\">&#60;?php</font>");
+          continue;
+        } else if (currentChar == '?' && isPHPTag() && currentPosition < input.length() && source[currentPosition] == '>') {
+          // php start tag
+          currentPosition += 4;
+          result.append("<font color=\"#7F0000\">?&#62;</font>");
+          continue;
+        } 
+        appendChar(result, currentChar);
+
+      }
+    } catch (IndexOutOfBoundsException e) {
+      if (identFound) {
+        currentPosition = appendIdentifier(input, identStart, currentPosition, keywordsSet, null, result);
+      }
+    }
+    result.append("</font>");
+    return result.toString();
+  }
+  /**
+   * @return Returns the KEYWORD_SET.
+   */
+  abstract public HashMap getKeywordSet();
+
+  /**
+   * @return Returns the OBJECT_SET.
+   */
+  abstract public HashSet getObjectSet();
+
+  public int getPriority() {
+    return 0;
+  }
+
+  /**
+   * @return Returns the KEYWORD_MAP.
+   */
+  public boolean isKeywordLowerCase() {
+    return true;
+  }
+
+  /**
+   *  
+   */
+  public boolean isPHPTag() {
+    return false;
+  }
+}
\ No newline at end of file
diff --git a/archive/org.plog4u.wiki/src/org/plog4u/wiki/macro/code/CHashCodeFilter.java b/archive/org.plog4u.wiki/src/org/plog4u/wiki/macro/code/CHashCodeFilter.java
new file mode 100644 (file)
index 0000000..9f48ddd
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ * 
+ * Please visit http://radeox.org/ for updates and contact.
+ * 
+ * --LICENSE NOTICE-- This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser
+ * General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any
+ * later version.
+ * 
+ * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA --LICENSE NOTICE--
+ */
+
+package org.plog4u.wiki.macro.code;
+
+import java.util.HashMap;
+import java.util.HashSet;
+
+import org.radeox.macro.code.SourceCodeFormatter;
+
+/**
+ * C# CodeFilter colourizes C# source code
+ *  
+ */
+public class CHashCodeFilter extends AbstractCPPBasedCodeFilter implements SourceCodeFormatter {
+
+  private static HashMap KEYWORD_SET = new HashMap();
+
+  private static final String[] KEYWORDS =
+    {
+      "class",
+      "abstract",
+      "event",
+      "new",
+      "struct",
+      "as",
+      "explicit",
+      "null",
+      "switch",
+      "base",
+      "extern",
+      "this",
+      "false",
+      "operator",
+      "throw",
+      "break",
+      "finally",
+      "out",
+      "true",
+      "fixed",
+      "override",
+      "try",
+      "case",
+      "float",
+      "params",
+      "typeof",
+      "catch",
+      "for",
+      "private",
+      "foreach",
+      "protected",
+      "checked",
+      "goto",
+      "public",
+      "unchecked",
+      "if",
+      "readonly",
+      "unsafe",
+      "const",
+      "implicit",
+      "ref",
+      "continue",
+      "in",
+      "return",
+      "using",
+      "virtual",
+      "default",
+      "interface",
+      "sealed",
+      "volatile",
+      "delegate",
+      "internal",
+      "do",
+      "is",
+      "sizeof",
+      "while",
+      "lock",
+      "stackalloc",
+      "else",
+      "static",
+      "enum",
+      "namespace",
+      };
+
+  private static final String[] OBJECT_WORDS =
+    {
+      "object",
+      "bool",
+      "byte",
+      "float",
+      "uint",
+      "char",
+      "ulong",
+      "ushort",
+      "decimal",
+      "int",
+      "sbyte",
+      "short",
+      "void",
+      "double",
+      "long",
+      "string" };
+  
+  private static HashSet OBJECT_SET = new HashSet();
+
+  {
+    for (int i = 0; i < KEYWORDS.length; i++) {
+      //KEYWORD_SET.put(KEYWORDS[i], ""+KEYWORDS[i]+"");
+      createHashMap(KEYWORD_SET, KEYWORDS[i]);
+    }
+    for (int i = 0; i < OBJECT_WORDS.length; i++) {
+      OBJECT_SET.add(OBJECT_WORDS[i]);
+    }
+  }
+
+  public CHashCodeFilter() {
+  }
+
+  /**
+   * @return Returns the KEYWORD_SET.
+   */
+  public HashMap getKeywordSet() {
+    return KEYWORD_SET;
+  }
+
+  public String getName() {
+    return "chash";
+  }
+
+  /**
+   * @return Returns the OBJECT_SET.
+   */
+  public HashSet getObjectSet() {
+    return OBJECT_SET;
+  }
+
+}
\ No newline at end of file
diff --git a/archive/org.plog4u.wiki/src/org/plog4u/wiki/macro/code/JavaCodeFilter.java b/archive/org.plog4u.wiki/src/org/plog4u/wiki/macro/code/JavaCodeFilter.java
new file mode 100644 (file)
index 0000000..5a56986
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * 
+ * Please visit http://radeox.org/ for updates and contact.
+ * 
+ * --LICENSE NOTICE-- This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser
+ * General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any
+ * later version.
+ * 
+ * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA --LICENSE NOTICE--
+ */
+
+package org.plog4u.wiki.macro.code;
+
+import java.util.HashMap;
+import java.util.HashSet;
+
+import org.radeox.macro.code.SourceCodeFormatter;
+
+/**
+ * Java CodeFilter colourizes C# source code
+ *  
+ */
+public class JavaCodeFilter extends AbstractCPPBasedCodeFilter implements SourceCodeFormatter {
+
+  private static HashMap KEYWORD_SET = new HashMap();
+
+  private static final String[] KEYWORDS =
+    {
+      "class",
+      "abstract",
+      "break",
+      "byvalue",
+      "case",
+      "cast",
+      "catch",
+      "const",
+      "continue",
+      "default",
+      "do",
+      "else",
+      "extends",
+      "false",
+      "final",
+      "finally",
+      "for",
+      "future",
+      "generic",
+      "goto",
+      "if",
+      "implements",
+      "import",
+      "inner",
+      "instanceof",
+      "interface",
+      "native",
+      "new",
+      "null",
+      "operator",
+      "outer",
+      "package",
+      "private",
+      "protected",
+      "public",
+      "rest",
+      "return",
+      "static",
+      "super",
+      "switch",
+      "synchronized",
+      "this",
+      "throw",
+      "throws",
+      "transient",
+      "true",
+      "try",
+      "var",
+      "volatile",
+      "while",
+      "assert",
+      "enum" };
+
+  private static final String[] OBJECT_WORDS =
+    {
+      "Boolean",
+      "Byte",
+      "Character",
+      "Class",
+      "ClassLoader",
+      "Cloneable",
+      "Compiler",
+      "Double",
+      "Float",
+      "Integer",
+      "Long",
+      "Math",
+      "Number",
+      "Object",
+      "Process",
+      "Runnable",
+      "Runtime",
+      "SecurityManager",
+      "Short",
+      "String",
+      "StringBuffer",
+      "System",
+      "Thread",
+      "ThreadGroup",
+      "Void",
+      "boolean",
+      "char",
+      "byte",
+      "short",
+      "int",
+      "long",
+      "float",
+      "double",
+      "void"};
+
+  private static HashSet OBJECT_SET = new HashSet();
+
+  {
+    for (int i = 0; i < KEYWORDS.length; i++) {
+      //KEYWORD_SET.put(KEYWORDS[i], ""+KEYWORDS[i]+"");
+      createHashMap(KEYWORD_SET, KEYWORDS[i]);
+    }
+    for (int i = 0; i < OBJECT_WORDS.length; i++) {
+      OBJECT_SET.add(OBJECT_WORDS[i]);
+    }
+  }
+
+  public JavaCodeFilter() {
+  }
+
+  /**
+   * @return Returns the KEYWORD_SET.
+   */
+  public HashMap getKeywordSet() {
+    return KEYWORD_SET;
+  }
+
+  public String getName() {
+    return "java";
+  }
+
+  /**
+   * @return Returns the OBJECT_SET.
+   */
+  public HashSet getObjectSet() {
+    return OBJECT_SET;
+  }
+
+}
\ No newline at end of file
diff --git a/archive/org.plog4u.wiki/src/org/plog4u/wiki/macro/code/NullCodeFilter.java b/archive/org.plog4u.wiki/src/org/plog4u/wiki/macro/code/NullCodeFilter.java
new file mode 100644 (file)
index 0000000..6182bf5
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * This file is part of "SnipSnap Radeox Rendering Engine".
+ *
+ * Copyright (c) 2002 Stephan J. Schmidt, Matthias L. Jugel
+ * All Rights Reserved.
+ *
+ * Please visit http://radeox.org/ for updates and contact.
+ *
+ * --LICENSE NOTICE--
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * --LICENSE NOTICE--
+ */
+
+package org.plog4u.wiki.macro.code;
+
+import org.radeox.filter.context.FilterContext;
+import org.radeox.macro.code.SourceCodeFormatter;
+
+/*
+ * Dummy filter that does nothing
+ *
+ * @author stephan
+ * @team sonicteam
+ * @version $Id: NullCodeFilter.java,v 1.1 2004-12-24 11:11:13 axelcl Exp $
+ */
+
+public class NullCodeFilter implements SourceCodeFormatter {
+
+  public NullCodeFilter() {
+  }
+
+  public String filter(String content, FilterContext context) {
+    return content;
+  }
+
+  public String getName() {
+    return "none";
+  }
+
+  public int getPriority() {
+    return 0;
+  }
+}
\ No newline at end of file
diff --git a/archive/org.plog4u.wiki/src/org/plog4u/wiki/macro/code/PHPCodeFilter.java b/archive/org.plog4u.wiki/src/org/plog4u/wiki/macro/code/PHPCodeFilter.java
new file mode 100644 (file)
index 0000000..81cbfc5
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ * 
+ * Please visit http://radeox.org/ for updates and contact.
+ * 
+ * --LICENSE NOTICE-- This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser
+ * General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any
+ * later version.
+ * 
+ * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA --LICENSE NOTICE--
+ */
+
+package org.plog4u.wiki.macro.code;
+
+import java.util.HashMap;
+import java.util.HashSet;
+
+import org.radeox.macro.code.SourceCodeFormatter;
+
+/**
+ * Java CodeFilter colourizes C# source code
+ *  
+ */
+public class PHPCodeFilter extends AbstractCPPBasedCodeFilter implements SourceCodeFormatter {
+
+  private static HashMap KEYWORD_SET = new HashMap();
+
+  private static final String[] KEYWORDS =
+    {
+      "if",
+      "elseif",
+      "else",
+      "endif",
+      "for",
+      "endfor",
+      "while",
+      "endwhile",
+      "switch",
+      "case",
+      "endswitch",
+      "break",
+      "continue",
+      "return",
+      "include",
+      "include_once",
+      "require",
+      "require_once",
+      "function",
+      "class",
+      "new",
+      "do",
+      "old_function",
+      "default",
+      "global",
+      "static",
+      "foreach",
+      "endforeach",
+      "extends",
+      "empty",
+      "array",
+      "echo",
+      "var",
+      "as",
+      "print",
+      "unset",
+      "exit",
+      "and",
+      "or",
+      "xor",
+      "list",
+      "null",
+      "false",
+      "true",
+      "abstract",
+      "catch",
+      "finally",
+      "try",
+      "private",
+      "protected",
+      "public",
+      "interface",
+      "implements",
+      "instanceof",
+      "super",
+      "throw",
+      "const",
+      "declare",
+      "enddeclare",
+      "eval",
+      "use",
+      "isset",
+      "final" };
+
+  {
+    for (int i = 0; i < KEYWORDS.length; i++) {
+      //KEYWORD_SET.put(KEYWORDS[i], ""+KEYWORDS[i]+"");
+      createHashMap(KEYWORD_SET, KEYWORDS[i]);
+    }
+
+  }
+
+  public PHPCodeFilter() {
+  }
+
+  /**
+   * @return Returns the KEYWORD_SET.
+   */
+  public HashMap getKeywordSet() {
+    return KEYWORD_SET;
+  }
+
+  public String getName() {
+    return "php";
+  }
+
+  /**
+   * @return Returns the OBJECT_SET.
+   */
+  public HashSet getObjectSet() {
+    return null;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see net.sourceforge.phpeclipse.wiki.macro.code.AbstractCPPBasedCodeFilter#isKeywordLowerCase()
+   */
+  public boolean isKeywordLowerCase() {
+    return false;
+  }
+  
+  /**
+   *  
+   */
+  public boolean isPHPTag() {
+    return true;
+  }
+}
\ No newline at end of file
diff --git a/archive/org.plog4u.wiki/src/org/plog4u/wiki/macro/code/SqlCodeFilter.java b/archive/org.plog4u.wiki/src/org/plog4u/wiki/macro/code/SqlCodeFilter.java
new file mode 100644 (file)
index 0000000..e1ace3b
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * This file is part of "SnipSnap Radeox Rendering Engine".
+ *
+ * Copyright (c) 2002 Stephan J. Schmidt, Matthias L. Jugel
+ * All Rights Reserved.
+ *
+ * Please visit http://radeox.org/ for updates and contact.
+ *
+ * --LICENSE NOTICE--
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * --LICENSE NOTICE--
+ */
+
+package org.plog4u.wiki.macro.code;
+
+import org.radeox.macro.code.DefaultRegexCodeFormatter;
+import org.radeox.macro.code.SourceCodeFormatter;
+
+/*
+ * SqlCodeFilter colourizes SQL source code
+ *
+ * @author stephan
+ * @team sonicteam
+ * @version $Id: SqlCodeFilter.java,v 1.1 2004-12-24 11:11:13 axelcl Exp $
+ */
+
+public class SqlCodeFilter extends DefaultRegexCodeFormatter implements SourceCodeFormatter {
+
+  private static final String KEYWORDS =
+      "\\b(SELECT|DELETE|UPDATE|WHERE|FROM|GROUP|BY|HAVING)\\b";
+
+  private static final String OBJECTS =
+      "\\b(VARCHAR)" +
+      "\\b";
+
+  private static final String QUOTES =
+      "\"(([^\"\\\\]|\\.)*)\"";
+
+
+  public SqlCodeFilter() {
+    super(QUOTES, "<b><font color=\"#2A00FF\">\"$1\"</font></b>");
+    addRegex(OBJECTS, "<b><font color=\"#7F9FBF\">$1</font></b>");
+    addRegex(KEYWORDS, "<b><font color=\"#750055\">$1</font></b>");
+  }
+
+
+  public String getName() {
+    return "sql";
+  }
+
+}
\ No newline at end of file
diff --git a/archive/org.plog4u.wiki/src/org/plog4u/wiki/macro/code/XmlCodeFilter.java b/archive/org.plog4u.wiki/src/org/plog4u/wiki/macro/code/XmlCodeFilter.java
new file mode 100644 (file)
index 0000000..237de19
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * This file is part of "SnipSnap Radeox Rendering Engine".
+ * 
+ * Copyright (c) 2002 Stephan J. Schmidt, Matthias L. Jugel All Rights Reserved.
+ * 
+ * Please visit http://radeox.org/ for updates and contact.
+ * 
+ * --LICENSE NOTICE-- This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser
+ * General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any
+ * later version.
+ * 
+ * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA --LICENSE NOTICE--
+ */
+package org.plog4u.wiki.macro.code;
+
+import org.radeox.macro.code.DefaultRegexCodeFormatter;
+import org.radeox.macro.code.SourceCodeFormatter;
+
+/*
+ * XmlCodeFilter colourizes Xml Code
+ * 
+ * @author stephan @team sonicteam
+ * 
+ * @version $Id: XmlCodeFilter.java,v 1.1 2004-12-24 11:11:13 axelcl Exp $
+ */
+
+public class XmlCodeFilter extends DefaultRegexCodeFormatter implements SourceCodeFormatter {
+  private static final String KEYWORDS = "\\b(xsl:[^&\\s]*)\\b";
+
+  private static final String TAGS = "(&#60;/?.*?&#62;)";
+
+  private static final String QUOTE = "\"(([^\"\\\\]|\\.)*)\"";
+
+  public XmlCodeFilter() {
+    super(QUOTE, "<b><font color=\"#2A00FF\">\"$1\"</font></b>");
+    addRegex(TAGS, "<b><font color=\"#7F9FBF\">$1</font></b>");
+    addRegex(KEYWORDS, "<b><font color=\"#750055\">$1</font></b>");
+  }
+
+  public String getName() {
+    return "xml";
+  }
+}
\ No newline at end of file