porting in progress
diff --git a/nbproject/build-impl.xml b/nbproject/build-impl.xml
new file mode 100644
index 0000000..e30d0ee
--- /dev/null
+++ b/nbproject/build-impl.xml
@@ -0,0 +1,1042 @@
+<?xml version="1.0" encoding="UTF-8"?>

+<!--

+*** GENERATED FROM project.xml - DO NOT EDIT  ***

+***         EDIT ../build.xml INSTEAD         ***

+

+For the purpose of easier reading the script

+is divided into following sections:

+

+  - initialization

+  - compilation

+  - jar

+  - execution

+  - debugging

+  - javadoc

+  - junit compilation

+  - junit execution

+  - junit debugging

+  - applet

+  - cleanup

+

+        -->

+<project xmlns:j2seproject1="http://www.netbeans.org/ns/j2se-project/1" xmlns:j2seproject3="http://www.netbeans.org/ns/j2se-project/3" xmlns:jaxrpc="http://www.netbeans.org/ns/j2se-project/jax-rpc" basedir=".." default="default" name="Prettify-impl">

+    <fail message="Please build using Ant 1.7.1 or higher.">

+        <condition>

+            <not>

+                <antversion atleast="1.7.1"/>

+            </not>

+        </condition>

+    </fail>

+    <target depends="test,jar,javadoc" description="Build and test whole project." name="default"/>

+    <!-- 

+                ======================

+                INITIALIZATION SECTION 

+                ======================

+            -->

+    <target name="-pre-init">

+        <!-- Empty placeholder for easier customization. -->

+        <!-- You can override this target in the ../build.xml file. -->

+    </target>

+    <target depends="-pre-init" name="-init-private">

+        <property file="nbproject/private/config.properties"/>

+        <property file="nbproject/private/configs/${config}.properties"/>

+        <property file="nbproject/private/private.properties"/>

+    </target>

+    <target depends="-pre-init,-init-private" name="-init-user">

+        <property file="${user.properties.file}"/>

+        <!-- The two properties below are usually overridden -->

+        <!-- by the active platform. Just a fallback. -->

+        <property name="default.javac.source" value="1.4"/>

+        <property name="default.javac.target" value="1.4"/>

+    </target>

+    <target depends="-pre-init,-init-private,-init-user" name="-init-project">

+        <property file="nbproject/configs/${config}.properties"/>

+        <property file="nbproject/project.properties"/>

+    </target>

+    <target depends="-pre-init,-init-private,-init-user,-init-project,-init-macrodef-property" name="-do-init">

+        <available file="${manifest.file}" property="manifest.available"/>

+        <condition property="splashscreen.available">

+            <and>

+                <not>

+                    <equals arg1="${application.splash}" arg2="" trim="true"/>

+                </not>

+                <available file="${application.splash}"/>

+            </and>

+        </condition>

+        <condition property="main.class.available">

+            <and>

+                <isset property="main.class"/>

+                <not>

+                    <equals arg1="${main.class}" arg2="" trim="true"/>

+                </not>

+            </and>

+        </condition>

+        <condition property="manifest.available+main.class">

+            <and>

+                <isset property="manifest.available"/>

+                <isset property="main.class.available"/>

+            </and>

+        </condition>

+        <condition property="do.archive">

+            <not>

+                <istrue value="${jar.archive.disabled}"/>

+            </not>

+        </condition>

+        <condition property="do.mkdist">

+            <and>

+                <isset property="do.archive"/>

+                <isset property="libs.CopyLibs.classpath"/>

+                <not>

+                    <istrue value="${mkdist.disabled}"/>

+                </not>

+            </and>

+        </condition>

+        <condition property="manifest.available+main.class+mkdist.available">

+            <and>

+                <istrue value="${manifest.available+main.class}"/>

+                <isset property="do.mkdist"/>

+            </and>

+        </condition>

+        <condition property="do.archive+manifest.available">

+            <and>

+                <isset property="manifest.available"/>

+                <istrue value="${do.archive}"/>

+            </and>

+        </condition>

+        <condition property="do.archive+main.class.available">

+            <and>

+                <isset property="main.class.available"/>

+                <istrue value="${do.archive}"/>

+            </and>

+        </condition>

+        <condition property="do.archive+splashscreen.available">

+            <and>

+                <isset property="splashscreen.available"/>

+                <istrue value="${do.archive}"/>

+            </and>

+        </condition>

+        <condition property="do.archive+manifest.available+main.class">

+            <and>

+                <istrue value="${manifest.available+main.class}"/>

+                <istrue value="${do.archive}"/>

+            </and>

+        </condition>

+        <condition property="manifest.available-mkdist.available">

+            <or>

+                <istrue value="${manifest.available}"/>

+                <isset property="do.mkdist"/>

+            </or>

+        </condition>

+        <condition property="manifest.available+main.class-mkdist.available">

+            <or>

+                <istrue value="${manifest.available+main.class}"/>

+                <isset property="do.mkdist"/>

+            </or>

+        </condition>

+        <condition property="have.tests">

+            <or>

+                <available file="${test.src.dir}"/>

+            </or>

+        </condition>

+        <condition property="have.sources">

+            <or>

+                <available file="${src.dir}"/>

+            </or>

+        </condition>

+        <condition property="netbeans.home+have.tests">

+            <and>

+                <isset property="netbeans.home"/>

+                <isset property="have.tests"/>

+            </and>

+        </condition>

+        <condition property="no.javadoc.preview">

+            <and>

+                <isset property="javadoc.preview"/>

+                <isfalse value="${javadoc.preview}"/>

+            </and>

+        </condition>

+        <property name="run.jvmargs" value=""/>

+        <property name="javac.compilerargs" value=""/>

+        <property name="work.dir" value="${basedir}"/>

+        <condition property="no.deps">

+            <and>

+                <istrue value="${no.dependencies}"/>

+            </and>

+        </condition>

+        <property name="javac.debug" value="true"/>

+        <property name="javadoc.preview" value="true"/>

+        <property name="application.args" value=""/>

+        <property name="source.encoding" value="${file.encoding}"/>

+        <property name="runtime.encoding" value="${source.encoding}"/>

+        <condition property="javadoc.encoding.used" value="${javadoc.encoding}">

+            <and>

+                <isset property="javadoc.encoding"/>

+                <not>

+                    <equals arg1="${javadoc.encoding}" arg2=""/>

+                </not>

+            </and>

+        </condition>

+        <property name="javadoc.encoding.used" value="${source.encoding}"/>

+        <property name="includes" value="**"/>

+        <property name="excludes" value=""/>

+        <property name="do.depend" value="false"/>

+        <condition property="do.depend.true">

+            <istrue value="${do.depend}"/>

+        </condition>

+        <path id="endorsed.classpath.path" path="${endorsed.classpath}"/>

+        <condition else="" property="endorsed.classpath.cmd.line.arg" value="-Xbootclasspath/p:'${toString:endorsed.classpath.path}'">

+            <length length="0" string="${endorsed.classpath}" when="greater"/>

+        </condition>

+        <condition else="false" property="jdkBug6558476">

+            <and>

+                <matches pattern="1\.[56]" string="${java.specification.version}"/>

+                <not>

+                    <os family="unix"/>

+                </not>

+            </and>

+        </condition>

+        <property name="javac.fork" value="${jdkBug6558476}"/>

+        <property name="jar.index" value="false"/>

+        <property name="jar.index.metainf" value="${jar.index}"/>

+        <available file="${meta.inf.dir}/persistence.xml" property="has.persistence.xml"/>

+    </target>

+    <target name="-post-init">

+        <!-- Empty placeholder for easier customization. -->

+        <!-- You can override this target in the ../build.xml file. -->

+    </target>

+    <target depends="-pre-init,-init-private,-init-user,-init-project,-do-init" name="-init-check">

+        <fail unless="src.dir">Must set src.dir</fail>

+        <fail unless="test.src.dir">Must set test.src.dir</fail>

+        <fail unless="build.dir">Must set build.dir</fail>

+        <fail unless="dist.dir">Must set dist.dir</fail>

+        <fail unless="build.classes.dir">Must set build.classes.dir</fail>

+        <fail unless="dist.javadoc.dir">Must set dist.javadoc.dir</fail>

+        <fail unless="build.test.classes.dir">Must set build.test.classes.dir</fail>

+        <fail unless="build.test.results.dir">Must set build.test.results.dir</fail>

+        <fail unless="build.classes.excludes">Must set build.classes.excludes</fail>

+        <fail unless="dist.jar">Must set dist.jar</fail>

+    </target>

+    <target name="-init-macrodef-property">

+        <macrodef name="property" uri="http://www.netbeans.org/ns/j2se-project/1">

+            <attribute name="name"/>

+            <attribute name="value"/>

+            <sequential>

+                <property name="@{name}" value="${@{value}}"/>

+            </sequential>

+        </macrodef>

+    </target>

+    <target depends="-init-ap-cmdline-properties" if="ap.supported.internal" name="-init-macrodef-javac-with-processors">

+        <macrodef name="javac" uri="http://www.netbeans.org/ns/j2se-project/3">

+            <attribute default="${src.dir}" name="srcdir"/>

+            <attribute default="${build.classes.dir}" name="destdir"/>

+            <attribute default="${javac.classpath}" name="classpath"/>

+            <attribute default="${javac.processorpath}" name="processorpath"/>

+            <attribute default="${build.generated.sources.dir}/ap-source-output" name="apgeneratedsrcdir"/>

+            <attribute default="${includes}" name="includes"/>

+            <attribute default="${excludes}" name="excludes"/>

+            <attribute default="${javac.debug}" name="debug"/>

+            <attribute default="${empty.dir}" name="sourcepath"/>

+            <attribute default="${empty.dir}" name="gensrcdir"/>

+            <element name="customize" optional="true"/>

+            <sequential>

+                <property location="${build.dir}/empty" name="empty.dir"/>

+                <mkdir dir="${empty.dir}"/>

+                <mkdir dir="@{apgeneratedsrcdir}"/>

+                <javac debug="@{debug}" deprecation="${javac.deprecation}" destdir="@{destdir}" encoding="${source.encoding}" excludes="@{excludes}" fork="${javac.fork}" includeantruntime="false" includes="@{includes}" source="${javac.source}" sourcepath="@{sourcepath}" srcdir="@{srcdir}" target="${javac.target}" tempdir="${java.io.tmpdir}">

+                    <src>

+                        <dirset dir="@{gensrcdir}" erroronmissingdir="false">

+                            <include name="*"/>

+                        </dirset>

+                    </src>

+                    <classpath>

+                        <path path="@{classpath}"/>

+                    </classpath>

+                    <compilerarg line="${endorsed.classpath.cmd.line.arg}"/>

+                    <compilerarg line="${javac.compilerargs}"/>

+                    <compilerarg value="-processorpath"/>

+                    <compilerarg path="@{processorpath}:${empty.dir}"/>

+                    <compilerarg line="${ap.processors.internal}"/>

+                    <compilerarg line="${annotation.processing.processor.options}"/>

+                    <compilerarg value="-s"/>

+                    <compilerarg path="@{apgeneratedsrcdir}"/>

+                    <compilerarg line="${ap.proc.none.internal}"/>

+                    <customize/>

+                </javac>

+            </sequential>

+        </macrodef>

+    </target>

+    <target depends="-init-ap-cmdline-properties" name="-init-macrodef-javac-without-processors" unless="ap.supported.internal">

+        <macrodef name="javac" uri="http://www.netbeans.org/ns/j2se-project/3">

+            <attribute default="${src.dir}" name="srcdir"/>

+            <attribute default="${build.classes.dir}" name="destdir"/>

+            <attribute default="${javac.classpath}" name="classpath"/>

+            <attribute default="${javac.processorpath}" name="processorpath"/>

+            <attribute default="${build.generated.sources.dir}/ap-source-output" name="apgeneratedsrcdir"/>

+            <attribute default="${includes}" name="includes"/>

+            <attribute default="${excludes}" name="excludes"/>

+            <attribute default="${javac.debug}" name="debug"/>

+            <attribute default="${empty.dir}" name="sourcepath"/>

+            <attribute default="${empty.dir}" name="gensrcdir"/>

+            <element name="customize" optional="true"/>

+            <sequential>

+                <property location="${build.dir}/empty" name="empty.dir"/>

+                <mkdir dir="${empty.dir}"/>

+                <javac debug="@{debug}" deprecation="${javac.deprecation}" destdir="@{destdir}" encoding="${source.encoding}" excludes="@{excludes}" fork="${javac.fork}" includeantruntime="false" includes="@{includes}" source="${javac.source}" sourcepath="@{sourcepath}" srcdir="@{srcdir}" target="${javac.target}" tempdir="${java.io.tmpdir}">

+                    <src>

+                        <dirset dir="@{gensrcdir}" erroronmissingdir="false">

+                            <include name="*"/>

+                        </dirset>

+                    </src>

+                    <classpath>

+                        <path path="@{classpath}"/>

+                    </classpath>

+                    <compilerarg line="${endorsed.classpath.cmd.line.arg}"/>

+                    <compilerarg line="${javac.compilerargs}"/>

+                    <customize/>

+                </javac>

+            </sequential>

+        </macrodef>

+    </target>

+    <target depends="-init-macrodef-javac-with-processors,-init-macrodef-javac-without-processors" name="-init-macrodef-javac">

+        <macrodef name="depend" uri="http://www.netbeans.org/ns/j2se-project/3">

+            <attribute default="${src.dir}" name="srcdir"/>

+            <attribute default="${build.classes.dir}" name="destdir"/>

+            <attribute default="${javac.classpath}" name="classpath"/>

+            <sequential>

+                <depend cache="${build.dir}/depcache" destdir="@{destdir}" excludes="${excludes}" includes="${includes}" srcdir="@{srcdir}">

+                    <classpath>

+                        <path path="@{classpath}"/>

+                    </classpath>

+                </depend>

+            </sequential>

+        </macrodef>

+        <macrodef name="force-recompile" uri="http://www.netbeans.org/ns/j2se-project/3">

+            <attribute default="${build.classes.dir}" name="destdir"/>

+            <sequential>

+                <fail unless="javac.includes">Must set javac.includes</fail>

+                <pathconvert pathsep="${line.separator}" property="javac.includes.binary">

+                    <path>

+                        <filelist dir="@{destdir}" files="${javac.includes}"/>

+                    </path>

+                    <globmapper from="*.java" to="*.class"/>

+                </pathconvert>

+                <tempfile deleteonexit="true" property="javac.includesfile.binary"/>

+                <echo file="${javac.includesfile.binary}" message="${javac.includes.binary}"/>

+                <delete>

+                    <files includesfile="${javac.includesfile.binary}"/>

+                </delete>

+                <delete>

+                    <fileset file="${javac.includesfile.binary}"/>

+                </delete>

+            </sequential>

+        </macrodef>

+    </target>

+    <target name="-init-macrodef-junit">

+        <macrodef name="junit" uri="http://www.netbeans.org/ns/j2se-project/3">

+            <attribute default="${includes}" name="includes"/>

+            <attribute default="${excludes}" name="excludes"/>

+            <attribute default="**" name="testincludes"/>

+            <sequential>

+                <property name="junit.forkmode" value="perTest"/>

+                <junit dir="${work.dir}" errorproperty="tests.failed" failureproperty="tests.failed" fork="true" forkmode="${junit.forkmode}" showoutput="true" tempdir="${build.dir}">

+                    <batchtest todir="${build.test.results.dir}">

+                        <fileset dir="${test.src.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">

+                            <filename name="@{testincludes}"/>

+                        </fileset>

+                    </batchtest>

+                    <classpath>

+                        <path path="${run.test.classpath}"/>

+                    </classpath>

+                    <syspropertyset>

+                        <propertyref prefix="test-sys-prop."/>

+                        <mapper from="test-sys-prop.*" to="*" type="glob"/>

+                    </syspropertyset>

+                    <formatter type="brief" usefile="false"/>

+                    <formatter type="xml"/>

+                    <jvmarg line="${endorsed.classpath.cmd.line.arg}"/>

+                    <jvmarg value="-ea"/>

+                    <jvmarg line="${run.jvmargs}"/>

+                </junit>

+            </sequential>

+        </macrodef>

+    </target>

+    <target depends="-profile-pre-init, init, -profile-post-init, -profile-init-macrodef-profile, -profile-init-check" name="profile-init"/>

+    <target name="-profile-pre-init">

+        <!-- Empty placeholder for easier customization. -->

+        <!-- You can override this target in the ../build.xml file. -->

+    </target>

+    <target name="-profile-post-init">

+        <!-- Empty placeholder for easier customization. -->

+        <!-- You can override this target in the ../build.xml file. -->

+    </target>

+    <target name="-profile-init-macrodef-profile">

+        <macrodef name="resolve">

+            <attribute name="name"/>

+            <attribute name="value"/>

+            <sequential>

+                <property name="@{name}" value="${env.@{value}}"/>

+            </sequential>

+        </macrodef>

+        <macrodef name="profile">

+            <attribute default="${main.class}" name="classname"/>

+            <element name="customize" optional="true"/>

+            <sequential>

+                <property environment="env"/>

+                <resolve name="profiler.current.path" value="${profiler.info.pathvar}"/>

+                <java classname="@{classname}" dir="${profiler.info.dir}" fork="true" jvm="${profiler.info.jvm}">

+                    <jvmarg value="${profiler.info.jvmargs.agent}"/>

+                    <jvmarg line="${profiler.info.jvmargs}"/>

+                    <env key="${profiler.info.pathvar}" path="${profiler.info.agentpath}:${profiler.current.path}"/>

+                    <arg line="${application.args}"/>

+                    <classpath>

+                        <path path="${run.classpath}"/>

+                    </classpath>

+                    <syspropertyset>

+                        <propertyref prefix="run-sys-prop."/>

+                        <mapper from="run-sys-prop.*" to="*" type="glob"/>

+                    </syspropertyset>

+                    <customize/>

+                </java>

+            </sequential>

+        </macrodef>

+    </target>

+    <target depends="-profile-pre-init, init, -profile-post-init, -profile-init-macrodef-profile" name="-profile-init-check">

+        <fail unless="profiler.info.jvm">Must set JVM to use for profiling in profiler.info.jvm</fail>

+        <fail unless="profiler.info.jvmargs.agent">Must set profiler agent JVM arguments in profiler.info.jvmargs.agent</fail>

+    </target>

+    <target depends="-init-debug-args" name="-init-macrodef-nbjpda">

+        <macrodef name="nbjpdastart" uri="http://www.netbeans.org/ns/j2se-project/1">

+            <attribute default="${main.class}" name="name"/>

+            <attribute default="${debug.classpath}" name="classpath"/>

+            <attribute default="" name="stopclassname"/>

+            <sequential>

+                <nbjpdastart addressproperty="jpda.address" name="@{name}" stopclassname="@{stopclassname}" transport="${debug-transport}">

+                    <classpath>

+                        <path path="@{classpath}"/>

+                    </classpath>

+                </nbjpdastart>

+            </sequential>

+        </macrodef>

+        <macrodef name="nbjpdareload" uri="http://www.netbeans.org/ns/j2se-project/1">

+            <attribute default="${build.classes.dir}" name="dir"/>

+            <sequential>

+                <nbjpdareload>

+                    <fileset dir="@{dir}" includes="${fix.classes}">

+                        <include name="${fix.includes}*.class"/>

+                    </fileset>

+                </nbjpdareload>

+            </sequential>

+        </macrodef>

+    </target>

+    <target name="-init-debug-args">

+        <property name="version-output" value="java version &quot;${ant.java.version}"/>

+        <condition property="have-jdk-older-than-1.4">

+            <or>

+                <contains string="${version-output}" substring="java version &quot;1.0"/>

+                <contains string="${version-output}" substring="java version &quot;1.1"/>

+                <contains string="${version-output}" substring="java version &quot;1.2"/>

+                <contains string="${version-output}" substring="java version &quot;1.3"/>

+            </or>

+        </condition>

+        <condition else="-Xdebug" property="debug-args-line" value="-Xdebug -Xnoagent -Djava.compiler=none">

+            <istrue value="${have-jdk-older-than-1.4}"/>

+        </condition>

+        <condition else="dt_socket" property="debug-transport-by-os" value="dt_shmem">

+            <os family="windows"/>

+        </condition>

+        <condition else="${debug-transport-by-os}" property="debug-transport" value="${debug.transport}">

+            <isset property="debug.transport"/>

+        </condition>

+    </target>

+    <target depends="-init-debug-args" name="-init-macrodef-debug">

+        <macrodef name="debug" uri="http://www.netbeans.org/ns/j2se-project/3">

+            <attribute default="${main.class}" name="classname"/>

+            <attribute default="${debug.classpath}" name="classpath"/>

+            <element name="customize" optional="true"/>

+            <sequential>

+                <java classname="@{classname}" dir="${work.dir}" fork="true">

+                    <jvmarg line="${endorsed.classpath.cmd.line.arg}"/>

+                    <jvmarg line="${debug-args-line}"/>

+                    <jvmarg value="-Xrunjdwp:transport=${debug-transport},address=${jpda.address}"/>

+                    <jvmarg value="-Dfile.encoding=${runtime.encoding}"/>

+                    <redirector errorencoding="${runtime.encoding}" inputencoding="${runtime.encoding}" outputencoding="${runtime.encoding}"/>

+                    <jvmarg line="${run.jvmargs}"/>

+                    <classpath>

+                        <path path="@{classpath}"/>

+                    </classpath>

+                    <syspropertyset>

+                        <propertyref prefix="run-sys-prop."/>

+                        <mapper from="run-sys-prop.*" to="*" type="glob"/>

+                    </syspropertyset>

+                    <customize/>

+                </java>

+            </sequential>

+        </macrodef>

+    </target>

+    <target name="-init-macrodef-java">

+        <macrodef name="java" uri="http://www.netbeans.org/ns/j2se-project/1">

+            <attribute default="${main.class}" name="classname"/>

+            <attribute default="${run.classpath}" name="classpath"/>

+            <element name="customize" optional="true"/>

+            <sequential>

+                <java classname="@{classname}" dir="${work.dir}" fork="true">

+                    <jvmarg line="${endorsed.classpath.cmd.line.arg}"/>

+                    <jvmarg value="-Dfile.encoding=${runtime.encoding}"/>

+                    <redirector errorencoding="${runtime.encoding}" inputencoding="${runtime.encoding}" outputencoding="${runtime.encoding}"/>

+                    <jvmarg line="${run.jvmargs}"/>

+                    <classpath>

+                        <path path="@{classpath}"/>

+                    </classpath>

+                    <syspropertyset>

+                        <propertyref prefix="run-sys-prop."/>

+                        <mapper from="run-sys-prop.*" to="*" type="glob"/>

+                    </syspropertyset>

+                    <customize/>

+                </java>

+            </sequential>

+        </macrodef>

+    </target>

+    <target name="-init-macrodef-copylibs">

+        <macrodef name="copylibs" uri="http://www.netbeans.org/ns/j2se-project/3">

+            <attribute default="${manifest.file}" name="manifest"/>

+            <element name="customize" optional="true"/>

+            <sequential>

+                <property location="${build.classes.dir}" name="build.classes.dir.resolved"/>

+                <pathconvert property="run.classpath.without.build.classes.dir">

+                    <path path="${run.classpath}"/>

+                    <map from="${build.classes.dir.resolved}" to=""/>

+                </pathconvert>

+                <pathconvert pathsep=" " property="jar.classpath">

+                    <path path="${run.classpath.without.build.classes.dir}"/>

+                    <chainedmapper>

+                        <flattenmapper/>

+                        <globmapper from="*" to="lib/*"/>

+                    </chainedmapper>

+                </pathconvert>

+                <taskdef classname="org.netbeans.modules.java.j2seproject.copylibstask.CopyLibs" classpath="${libs.CopyLibs.classpath}" name="copylibs"/>

+                <copylibs compress="${jar.compress}" index="${jar.index}" indexMetaInf="${jar.index.metainf}" jarfile="${dist.jar}" manifest="@{manifest}" runtimeclasspath="${run.classpath.without.build.classes.dir}">

+                    <fileset dir="${build.classes.dir}"/>

+                    <manifest>

+                        <attribute name="Class-Path" value="${jar.classpath}"/>

+                        <customize/>

+                    </manifest>

+                </copylibs>

+            </sequential>

+        </macrodef>

+    </target>

+    <target name="-init-presetdef-jar">

+        <presetdef name="jar" uri="http://www.netbeans.org/ns/j2se-project/1">

+            <jar compress="${jar.compress}" index="${jar.index}" jarfile="${dist.jar}">

+                <j2seproject1:fileset dir="${build.classes.dir}"/>

+            </jar>

+        </presetdef>

+    </target>

+    <target name="-init-ap-cmdline-properties">

+        <property name="annotation.processing.enabled" value="true"/>

+        <property name="annotation.processing.processors.list" value=""/>

+        <property name="annotation.processing.processor.options" value=""/>

+        <property name="annotation.processing.run.all.processors" value="true"/>

+        <property name="javac.processorpath" value="${javac.classpath}"/>

+        <property name="javac.test.processorpath" value="${javac.test.classpath}"/>

+        <condition property="ap.supported.internal" value="true">

+            <not>

+                <matches pattern="1\.[0-5](\..*)?" string="${javac.source}"/>

+            </not>

+        </condition>

+    </target>

+    <target depends="-init-ap-cmdline-properties" if="ap.supported.internal" name="-init-ap-cmdline-supported">

+        <condition else="" property="ap.processors.internal" value="-processor ${annotation.processing.processors.list}">

+            <isfalse value="${annotation.processing.run.all.processors}"/>

+        </condition>

+        <condition else="" property="ap.proc.none.internal" value="-proc:none">

+            <isfalse value="${annotation.processing.enabled}"/>

+        </condition>

+    </target>

+    <target depends="-init-ap-cmdline-properties,-init-ap-cmdline-supported" name="-init-ap-cmdline">

+        <property name="ap.cmd.line.internal" value=""/>

+    </target>

+    <target depends="-pre-init,-init-private,-init-user,-init-project,-do-init,-post-init,-init-check,-init-macrodef-property,-init-macrodef-javac,-init-macrodef-junit,-init-macrodef-nbjpda,-init-macrodef-debug,-init-macrodef-java,-init-presetdef-jar,-init-ap-cmdline" name="init"/>

+    <!--

+                ===================

+                COMPILATION SECTION

+                ===================

+            -->

+    <target name="-deps-jar-init" unless="built-jar.properties">

+        <property location="${build.dir}/built-jar.properties" name="built-jar.properties"/>

+        <delete file="${built-jar.properties}" quiet="true"/>

+    </target>

+    <target if="already.built.jar.${basedir}" name="-warn-already-built-jar">

+        <echo level="warn" message="Cycle detected: Prettify was already built"/>

+    </target>

+    <target depends="init,-deps-jar-init" name="deps-jar" unless="no.deps">

+        <mkdir dir="${build.dir}"/>

+        <touch file="${built-jar.properties}" verbose="false"/>

+        <property file="${built-jar.properties}" prefix="already.built.jar."/>

+        <antcall target="-warn-already-built-jar"/>

+        <propertyfile file="${built-jar.properties}">

+            <entry key="${basedir}" value=""/>

+        </propertyfile>

+    </target>

+    <target depends="init,-check-automatic-build,-clean-after-automatic-build" name="-verify-automatic-build"/>

+    <target depends="init" name="-check-automatic-build">

+        <available file="${build.classes.dir}/.netbeans_automatic_build" property="netbeans.automatic.build"/>

+    </target>

+    <target depends="init" if="netbeans.automatic.build" name="-clean-after-automatic-build">

+        <antcall target="clean"/>

+    </target>

+    <target depends="init,deps-jar" name="-pre-pre-compile">

+        <mkdir dir="${build.classes.dir}"/>

+    </target>

+    <target name="-pre-compile">

+        <!-- Empty placeholder for easier customization. -->

+        <!-- You can override this target in the ../build.xml file. -->

+    </target>

+    <target if="do.depend.true" name="-compile-depend">

+        <pathconvert property="build.generated.subdirs">

+            <dirset dir="${build.generated.sources.dir}" erroronmissingdir="false">

+                <include name="*"/>

+            </dirset>

+        </pathconvert>

+        <j2seproject3:depend srcdir="${src.dir}:${build.generated.subdirs}"/>

+    </target>

+    <target depends="init,deps-jar,-pre-pre-compile,-pre-compile, -copy-persistence-xml,-compile-depend" if="have.sources" name="-do-compile">

+        <j2seproject3:javac gensrcdir="${build.generated.sources.dir}"/>

+        <copy todir="${build.classes.dir}">

+            <fileset dir="${src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>

+        </copy>

+    </target>

+    <target if="has.persistence.xml" name="-copy-persistence-xml">

+        <mkdir dir="${build.classes.dir}/META-INF"/>

+        <copy todir="${build.classes.dir}/META-INF">

+            <fileset dir="${meta.inf.dir}" includes="persistence.xml"/>

+        </copy>

+    </target>

+    <target name="-post-compile">

+        <!-- Empty placeholder for easier customization. -->

+        <!-- You can override this target in the ../build.xml file. -->

+    </target>

+    <target depends="init,deps-jar,-verify-automatic-build,-pre-pre-compile,-pre-compile,-do-compile,-post-compile" description="Compile project." name="compile"/>

+    <target name="-pre-compile-single">

+        <!-- Empty placeholder for easier customization. -->

+        <!-- You can override this target in the ../build.xml file. -->

+    </target>

+    <target depends="init,deps-jar,-pre-pre-compile" name="-do-compile-single">

+        <fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail>

+        <j2seproject3:force-recompile/>

+        <j2seproject3:javac excludes="" gensrcdir="${build.generated.sources.dir}" includes="${javac.includes}" sourcepath="${src.dir}"/>

+    </target>

+    <target name="-post-compile-single">

+        <!-- Empty placeholder for easier customization. -->

+        <!-- You can override this target in the ../build.xml file. -->

+    </target>

+    <target depends="init,deps-jar,-verify-automatic-build,-pre-pre-compile,-pre-compile-single,-do-compile-single,-post-compile-single" name="compile-single"/>

+    <!--

+                ====================

+                JAR BUILDING SECTION

+                ====================

+            -->

+    <target depends="init" name="-pre-pre-jar">

+        <dirname file="${dist.jar}" property="dist.jar.dir"/>

+        <mkdir dir="${dist.jar.dir}"/>

+    </target>

+    <target name="-pre-jar">

+        <!-- Empty placeholder for easier customization. -->

+        <!-- You can override this target in the ../build.xml file. -->

+    </target>

+    <target depends="init,compile,-pre-pre-jar,-pre-jar" if="do.archive" name="-do-jar-without-manifest" unless="manifest.available-mkdist.available">

+        <j2seproject1:jar/>

+    </target>

+    <target depends="init,compile,-pre-pre-jar,-pre-jar" if="do.archive+manifest.available" name="-do-jar-with-manifest" unless="manifest.available+main.class-mkdist.available">

+        <j2seproject1:jar manifest="${manifest.file}"/>

+    </target>

+    <target depends="init,compile,-pre-pre-jar,-pre-jar" if="do.archive+manifest.available+main.class" name="-do-jar-with-mainclass" unless="manifest.available+main.class+mkdist.available">

+        <j2seproject1:jar manifest="${manifest.file}">

+            <j2seproject1:manifest>

+                <j2seproject1:attribute name="Main-Class" value="${main.class}"/>

+            </j2seproject1:manifest>

+        </j2seproject1:jar>

+        <echo level="info">To run this application from the command line without Ant, try:</echo>

+        <property location="${build.classes.dir}" name="build.classes.dir.resolved"/>

+        <property location="${dist.jar}" name="dist.jar.resolved"/>

+        <pathconvert property="run.classpath.with.dist.jar">

+            <path path="${run.classpath}"/>

+            <map from="${build.classes.dir.resolved}" to="${dist.jar.resolved}"/>

+        </pathconvert>

+        <echo level="info">java -cp "${run.classpath.with.dist.jar}" ${main.class}</echo>

+    </target>

+    <target depends="init" if="do.archive" name="-do-jar-with-libraries-create-manifest" unless="manifest.available">

+        <tempfile deleteonexit="true" destdir="${build.dir}" property="tmp.manifest.file"/>

+        <touch file="${tmp.manifest.file}" verbose="false"/>

+    </target>

+    <target depends="init" if="do.archive+manifest.available" name="-do-jar-with-libraries-copy-manifest">

+        <tempfile deleteonexit="true" destdir="${build.dir}" property="tmp.manifest.file"/>

+        <copy file="${manifest.file}" tofile="${tmp.manifest.file}"/>

+    </target>

+    <target depends="init,-do-jar-with-libraries-create-manifest,-do-jar-with-libraries-copy-manifest" if="do.archive+main.class.available" name="-do-jar-with-libraries-set-main">

+        <manifest file="${tmp.manifest.file}" mode="update">

+            <attribute name="Main-Class" value="${main.class}"/>

+        </manifest>

+    </target>

+    <target depends="init,-do-jar-with-libraries-create-manifest,-do-jar-with-libraries-copy-manifest" if="do.archive+splashscreen.available" name="-do-jar-with-libraries-set-splashscreen">

+        <basename file="${application.splash}" property="splashscreen.basename"/>

+        <mkdir dir="${build.classes.dir}/META-INF"/>

+        <copy failonerror="false" file="${application.splash}" todir="${build.classes.dir}/META-INF"/>

+        <manifest file="${tmp.manifest.file}" mode="update">

+            <attribute name="SplashScreen-Image" value="META-INF/${splashscreen.basename}"/>

+        </manifest>

+    </target>

+    <target depends="init,-init-macrodef-copylibs,compile,-pre-pre-jar,-pre-jar,-do-jar-with-libraries-create-manifest,-do-jar-with-libraries-copy-manifest,-do-jar-with-libraries-set-main,-do-jar-with-libraries-set-splashscreen" if="do.mkdist" name="-do-jar-with-libraries-pack">

+        <j2seproject3:copylibs manifest="${tmp.manifest.file}"/>

+        <echo level="info">To run this application from the command line without Ant, try:</echo>

+        <property location="${dist.jar}" name="dist.jar.resolved"/>

+        <echo level="info">java -jar "${dist.jar.resolved}"</echo>

+    </target>

+    <target depends="-do-jar-with-libraries-pack" if="do.archive" name="-do-jar-with-libraries-delete-manifest">

+        <delete>

+            <fileset file="${tmp.manifest.file}"/>

+        </delete>

+    </target>

+    <target depends="init,compile,-pre-pre-jar,-pre-jar,-do-jar-with-libraries-create-manifest,-do-jar-with-libraries-copy-manifest,-do-jar-with-libraries-set-main,-do-jar-with-libraries-set-splashscreen,-do-jar-with-libraries-pack,-do-jar-with-libraries-delete-manifest" name="-do-jar-with-libraries"/>

+    <target name="-post-jar">

+        <!-- Empty placeholder for easier customization. -->

+        <!-- You can override this target in the ../build.xml file. -->

+    </target>

+    <target depends="init,compile,-pre-jar,-do-jar-with-manifest,-do-jar-without-manifest,-do-jar-with-mainclass,-do-jar-with-libraries,-post-jar" description="Build JAR." name="jar"/>

+    <!--

+                =================

+                EXECUTION SECTION

+                =================

+            -->

+    <target depends="init,compile" description="Run a main class." name="run">

+        <j2seproject1:java>

+            <customize>

+                <arg line="${application.args}"/>

+            </customize>

+        </j2seproject1:java>

+    </target>

+    <target name="-do-not-recompile">

+        <property name="javac.includes.binary" value=""/>

+    </target>

+    <target depends="init,compile-single" name="run-single">

+        <fail unless="run.class">Must select one file in the IDE or set run.class</fail>

+        <j2seproject1:java classname="${run.class}"/>

+    </target>

+    <target depends="init,compile-test-single" name="run-test-with-main">

+        <fail unless="run.class">Must select one file in the IDE or set run.class</fail>

+        <j2seproject1:java classname="${run.class}" classpath="${run.test.classpath}"/>

+    </target>

+    <!--

+                =================

+                DEBUGGING SECTION

+                =================

+            -->

+    <target depends="init" if="netbeans.home" name="-debug-start-debugger">

+        <j2seproject1:nbjpdastart name="${debug.class}"/>

+    </target>

+    <target depends="init" if="netbeans.home" name="-debug-start-debugger-main-test">

+        <j2seproject1:nbjpdastart classpath="${debug.test.classpath}" name="${debug.class}"/>

+    </target>

+    <target depends="init,compile" name="-debug-start-debuggee">

+        <j2seproject3:debug>

+            <customize>

+                <arg line="${application.args}"/>

+            </customize>

+        </j2seproject3:debug>

+    </target>

+    <target depends="init,compile,-debug-start-debugger,-debug-start-debuggee" description="Debug project in IDE." if="netbeans.home" name="debug"/>

+    <target depends="init" if="netbeans.home" name="-debug-start-debugger-stepinto">

+        <j2seproject1:nbjpdastart stopclassname="${main.class}"/>

+    </target>

+    <target depends="init,compile,-debug-start-debugger-stepinto,-debug-start-debuggee" if="netbeans.home" name="debug-stepinto"/>

+    <target depends="init,compile-single" if="netbeans.home" name="-debug-start-debuggee-single">

+        <fail unless="debug.class">Must select one file in the IDE or set debug.class</fail>

+        <j2seproject3:debug classname="${debug.class}"/>

+    </target>

+    <target depends="init,compile-single,-debug-start-debugger,-debug-start-debuggee-single" if="netbeans.home" name="debug-single"/>

+    <target depends="init,compile-test-single" if="netbeans.home" name="-debug-start-debuggee-main-test">

+        <fail unless="debug.class">Must select one file in the IDE or set debug.class</fail>

+        <j2seproject3:debug classname="${debug.class}" classpath="${debug.test.classpath}"/>

+    </target>

+    <target depends="init,compile-test-single,-debug-start-debugger-main-test,-debug-start-debuggee-main-test" if="netbeans.home" name="debug-test-with-main"/>

+    <target depends="init" name="-pre-debug-fix">

+        <fail unless="fix.includes">Must set fix.includes</fail>

+        <property name="javac.includes" value="${fix.includes}.java"/>

+    </target>

+    <target depends="init,-pre-debug-fix,compile-single" if="netbeans.home" name="-do-debug-fix">

+        <j2seproject1:nbjpdareload/>

+    </target>

+    <target depends="init,-pre-debug-fix,-do-debug-fix" if="netbeans.home" name="debug-fix"/>

+    <!--

+                =================

+                PROFILING SECTION

+                =================

+            -->

+    <target depends="profile-init,compile" description="Profile a project in the IDE." if="netbeans.home" name="profile">

+        <nbprofiledirect>

+            <classpath>

+                <path path="${run.classpath}"/>

+            </classpath>

+        </nbprofiledirect>

+        <profile/>

+    </target>

+    <target depends="profile-init,compile-single" description="Profile a selected class in the IDE." if="netbeans.home" name="profile-single">

+        <fail unless="profile.class">Must select one file in the IDE or set profile.class</fail>

+        <nbprofiledirect>

+            <classpath>

+                <path path="${run.classpath}"/>

+            </classpath>

+        </nbprofiledirect>

+        <profile classname="${profile.class}"/>

+    </target>

+    <!--

+                =========================

+                APPLET PROFILING  SECTION

+                =========================

+            -->

+    <target depends="profile-init,compile-single" if="netbeans.home" name="profile-applet">

+        <nbprofiledirect>

+            <classpath>

+                <path path="${run.classpath}"/>

+            </classpath>

+        </nbprofiledirect>

+        <profile classname="sun.applet.AppletViewer">

+            <customize>

+                <arg value="${applet.url}"/>

+            </customize>

+        </profile>

+    </target>

+    <!--

+                =========================

+                TESTS PROFILING  SECTION

+                =========================

+            -->

+    <target depends="profile-init,compile-test-single" if="netbeans.home" name="profile-test-single">

+        <nbprofiledirect>

+            <classpath>

+                <path path="${run.test.classpath}"/>

+            </classpath>

+        </nbprofiledirect>

+        <junit dir="${profiler.info.dir}" errorproperty="tests.failed" failureproperty="tests.failed" fork="true" jvm="${profiler.info.jvm}" showoutput="true">

+            <env key="${profiler.info.pathvar}" path="${profiler.info.agentpath}:${profiler.current.path}"/>

+            <jvmarg value="${profiler.info.jvmargs.agent}"/>

+            <jvmarg line="${profiler.info.jvmargs}"/>

+            <test name="${profile.class}"/>

+            <classpath>

+                <path path="${run.test.classpath}"/>

+            </classpath>

+            <syspropertyset>

+                <propertyref prefix="test-sys-prop."/>

+                <mapper from="test-sys-prop.*" to="*" type="glob"/>

+            </syspropertyset>

+            <formatter type="brief" usefile="false"/>

+            <formatter type="xml"/>

+        </junit>

+    </target>

+    <!--

+                ===============

+                JAVADOC SECTION

+                ===============

+            -->

+    <target depends="init" if="have.sources" name="-javadoc-build">

+        <mkdir dir="${dist.javadoc.dir}"/>

+        <javadoc additionalparam="${javadoc.additionalparam}" author="${javadoc.author}" charset="UTF-8" destdir="${dist.javadoc.dir}" docencoding="UTF-8" encoding="${javadoc.encoding.used}" failonerror="true" noindex="${javadoc.noindex}" nonavbar="${javadoc.nonavbar}" notree="${javadoc.notree}" private="${javadoc.private}" source="${javac.source}" splitindex="${javadoc.splitindex}" use="${javadoc.use}" useexternalfile="true" version="${javadoc.version}" windowtitle="${javadoc.windowtitle}">

+            <classpath>

+                <path path="${javac.classpath}"/>

+            </classpath>

+            <fileset dir="${src.dir}" excludes="*.java,${excludes}" includes="${includes}">

+                <filename name="**/*.java"/>

+            </fileset>

+            <fileset dir="${build.generated.sources.dir}" erroronmissingdir="false">

+                <include name="**/*.java"/>

+                <exclude name="*.java"/>

+            </fileset>

+        </javadoc>

+        <copy todir="${dist.javadoc.dir}">

+            <fileset dir="${src.dir}" excludes="${excludes}" includes="${includes}">

+                <filename name="**/doc-files/**"/>

+            </fileset>

+            <fileset dir="${build.generated.sources.dir}" erroronmissingdir="false">

+                <include name="**/doc-files/**"/>

+            </fileset>

+        </copy>

+    </target>

+    <target depends="init,-javadoc-build" if="netbeans.home" name="-javadoc-browse" unless="no.javadoc.preview">

+        <nbbrowse file="${dist.javadoc.dir}/index.html"/>

+    </target>

+    <target depends="init,-javadoc-build,-javadoc-browse" description="Build Javadoc." name="javadoc"/>

+    <!--

+                =========================

+                JUNIT COMPILATION SECTION

+                =========================

+            -->

+    <target depends="init,compile" if="have.tests" name="-pre-pre-compile-test">

+        <mkdir dir="${build.test.classes.dir}"/>

+    </target>

+    <target name="-pre-compile-test">

+        <!-- Empty placeholder for easier customization. -->

+        <!-- You can override this target in the ../build.xml file. -->

+    </target>

+    <target if="do.depend.true" name="-compile-test-depend">

+        <j2seproject3:depend classpath="${javac.test.classpath}" destdir="${build.test.classes.dir}" srcdir="${test.src.dir}"/>

+    </target>

+    <target depends="init,deps-jar,compile,-pre-pre-compile-test,-pre-compile-test,-compile-test-depend" if="have.tests" name="-do-compile-test">

+        <j2seproject3:javac apgeneratedsrcdir="${build.test.classes.dir}" classpath="${javac.test.classpath}" debug="true" destdir="${build.test.classes.dir}" processorpath="${javac.test.processorpath}" srcdir="${test.src.dir}"/>

+        <copy todir="${build.test.classes.dir}">

+            <fileset dir="${test.src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>

+        </copy>

+    </target>

+    <target name="-post-compile-test">

+        <!-- Empty placeholder for easier customization. -->

+        <!-- You can override this target in the ../build.xml file. -->

+    </target>

+    <target depends="init,compile,-pre-pre-compile-test,-pre-compile-test,-do-compile-test,-post-compile-test" name="compile-test"/>

+    <target name="-pre-compile-test-single">

+        <!-- Empty placeholder for easier customization. -->

+        <!-- You can override this target in the ../build.xml file. -->

+    </target>

+    <target depends="init,deps-jar,compile,-pre-pre-compile-test,-pre-compile-test-single" if="have.tests" name="-do-compile-test-single">

+        <fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail>

+        <j2seproject3:force-recompile destdir="${build.test.classes.dir}"/>

+        <j2seproject3:javac apgeneratedsrcdir="${build.test.classes.dir}" classpath="${javac.test.classpath}" debug="true" destdir="${build.test.classes.dir}" excludes="" includes="${javac.includes}" processorpath="${javac.test.processorpath}" sourcepath="${test.src.dir}" srcdir="${test.src.dir}"/>

+        <copy todir="${build.test.classes.dir}">

+            <fileset dir="${test.src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>

+        </copy>

+    </target>

+    <target name="-post-compile-test-single">

+        <!-- Empty placeholder for easier customization. -->

+        <!-- You can override this target in the ../build.xml file. -->

+    </target>

+    <target depends="init,compile,-pre-pre-compile-test,-pre-compile-test-single,-do-compile-test-single,-post-compile-test-single" name="compile-test-single"/>

+    <!--

+                =======================

+                JUNIT EXECUTION SECTION

+                =======================

+            -->

+    <target depends="init" if="have.tests" name="-pre-test-run">

+        <mkdir dir="${build.test.results.dir}"/>

+    </target>

+    <target depends="init,compile-test,-pre-test-run" if="have.tests" name="-do-test-run">

+        <j2seproject3:junit testincludes="**/*Test.java"/>

+    </target>

+    <target depends="init,compile-test,-pre-test-run,-do-test-run" if="have.tests" name="-post-test-run">

+        <fail if="tests.failed" unless="ignore.failing.tests">Some tests failed; see details above.</fail>

+    </target>

+    <target depends="init" if="have.tests" name="test-report"/>

+    <target depends="init" if="netbeans.home+have.tests" name="-test-browse"/>

+    <target depends="init,compile-test,-pre-test-run,-do-test-run,test-report,-post-test-run,-test-browse" description="Run unit tests." name="test"/>

+    <target depends="init" if="have.tests" name="-pre-test-run-single">

+        <mkdir dir="${build.test.results.dir}"/>

+    </target>

+    <target depends="init,compile-test-single,-pre-test-run-single" if="have.tests" name="-do-test-run-single">

+        <fail unless="test.includes">Must select some files in the IDE or set test.includes</fail>

+        <j2seproject3:junit excludes="" includes="${test.includes}"/>

+    </target>

+    <target depends="init,compile-test-single,-pre-test-run-single,-do-test-run-single" if="have.tests" name="-post-test-run-single">

+        <fail if="tests.failed" unless="ignore.failing.tests">Some tests failed; see details above.</fail>

+    </target>

+    <target depends="init,compile-test-single,-pre-test-run-single,-do-test-run-single,-post-test-run-single" description="Run single unit test." name="test-single"/>

+    <!--

+                =======================

+                JUNIT DEBUGGING SECTION

+                =======================

+            -->

+    <target depends="init,compile-test" if="have.tests" name="-debug-start-debuggee-test">

+        <fail unless="test.class">Must select one file in the IDE or set test.class</fail>

+        <property location="${build.test.results.dir}/TEST-${test.class}.xml" name="test.report.file"/>

+        <delete file="${test.report.file}"/>

+        <mkdir dir="${build.test.results.dir}"/>

+        <j2seproject3:debug classname="org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner" classpath="${ant.home}/lib/ant.jar:${ant.home}/lib/ant-junit.jar:${debug.test.classpath}">

+            <customize>

+                <syspropertyset>

+                    <propertyref prefix="test-sys-prop."/>

+                    <mapper from="test-sys-prop.*" to="*" type="glob"/>

+                </syspropertyset>

+                <arg value="${test.class}"/>

+                <arg value="showoutput=true"/>

+                <arg value="formatter=org.apache.tools.ant.taskdefs.optional.junit.BriefJUnitResultFormatter"/>

+                <arg value="formatter=org.apache.tools.ant.taskdefs.optional.junit.XMLJUnitResultFormatter,${test.report.file}"/>

+            </customize>

+        </j2seproject3:debug>

+    </target>

+    <target depends="init,compile-test" if="netbeans.home+have.tests" name="-debug-start-debugger-test">

+        <j2seproject1:nbjpdastart classpath="${debug.test.classpath}" name="${test.class}"/>

+    </target>

+    <target depends="init,compile-test-single,-debug-start-debugger-test,-debug-start-debuggee-test" name="debug-test"/>

+    <target depends="init,-pre-debug-fix,compile-test-single" if="netbeans.home" name="-do-debug-fix-test">

+        <j2seproject1:nbjpdareload dir="${build.test.classes.dir}"/>

+    </target>

+    <target depends="init,-pre-debug-fix,-do-debug-fix-test" if="netbeans.home" name="debug-fix-test"/>

+    <!--

+                =========================

+                APPLET EXECUTION SECTION

+                =========================

+            -->

+    <target depends="init,compile-single" name="run-applet">

+        <fail unless="applet.url">Must select one file in the IDE or set applet.url</fail>

+        <j2seproject1:java classname="sun.applet.AppletViewer">

+            <customize>

+                <arg value="${applet.url}"/>

+            </customize>

+        </j2seproject1:java>

+    </target>

+    <!--

+                =========================

+                APPLET DEBUGGING  SECTION

+                =========================

+            -->

+    <target depends="init,compile-single" if="netbeans.home" name="-debug-start-debuggee-applet">

+        <fail unless="applet.url">Must select one file in the IDE or set applet.url</fail>

+        <j2seproject3:debug classname="sun.applet.AppletViewer">

+            <customize>

+                <arg value="${applet.url}"/>

+            </customize>

+        </j2seproject3:debug>

+    </target>

+    <target depends="init,compile-single,-debug-start-debugger,-debug-start-debuggee-applet" if="netbeans.home" name="debug-applet"/>

+    <!--

+                ===============

+                CLEANUP SECTION

+                ===============

+            -->

+    <target name="-deps-clean-init" unless="built-clean.properties">

+        <property location="${build.dir}/built-clean.properties" name="built-clean.properties"/>

+        <delete file="${built-clean.properties}" quiet="true"/>

+    </target>

+    <target if="already.built.clean.${basedir}" name="-warn-already-built-clean">

+        <echo level="warn" message="Cycle detected: Prettify was already built"/>

+    </target>

+    <target depends="init,-deps-clean-init" name="deps-clean" unless="no.deps">

+        <mkdir dir="${build.dir}"/>

+        <touch file="${built-clean.properties}" verbose="false"/>

+        <property file="${built-clean.properties}" prefix="already.built.clean."/>

+        <antcall target="-warn-already-built-clean"/>

+        <propertyfile file="${built-clean.properties}">

+            <entry key="${basedir}" value=""/>

+        </propertyfile>

+    </target>

+    <target depends="init" name="-do-clean">

+        <delete dir="${build.dir}"/>

+        <delete dir="${dist.dir}" followsymlinks="false" includeemptydirs="true"/>

+    </target>

+    <target name="-post-clean">

+        <!-- Empty placeholder for easier customization. -->

+        <!-- You can override this target in the ../build.xml file. -->

+    </target>

+    <target depends="init,deps-clean,-do-clean,-post-clean" description="Clean build products." name="clean"/>

+    <target name="-check-call-dep">

+        <property file="${call.built.properties}" prefix="already.built."/>

+        <condition property="should.call.dep">

+            <not>

+                <isset property="already.built.${call.subproject}"/>

+            </not>

+        </condition>

+    </target>

+    <target depends="-check-call-dep" if="should.call.dep" name="-maybe-call-dep">

+        <ant antfile="${call.script}" inheritall="false" target="${call.target}">

+            <propertyset>

+                <propertyref prefix="transfer."/>

+                <mapper from="transfer.*" to="*" type="glob"/>

+            </propertyset>

+        </ant>

+    </target>

+</project>

diff --git a/nbproject/genfiles.properties b/nbproject/genfiles.properties
new file mode 100644
index 0000000..cde3213
--- /dev/null
+++ b/nbproject/genfiles.properties
@@ -0,0 +1,8 @@
+build.xml.data.CRC32=4d2699c2

+build.xml.script.CRC32=fd9caa3f

+build.xml.stylesheet.CRC32=28e38971@1.44.1.45

+# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.

+# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.

+nbproject/build-impl.xml.data.CRC32=4d2699c2

+nbproject/build-impl.xml.script.CRC32=95d36cae

+nbproject/build-impl.xml.stylesheet.CRC32=0ae3a408@1.44.1.45

diff --git a/nbproject/project.properties b/nbproject/project.properties
new file mode 100644
index 0000000..f4a767d
--- /dev/null
+++ b/nbproject/project.properties
@@ -0,0 +1,71 @@
+annotation.processing.enabled=true

+annotation.processing.enabled.in.editor=false

+annotation.processing.processor.options=

+annotation.processing.processors.list=

+annotation.processing.run.all.processors=true

+annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output

+build.classes.dir=${build.dir}/classes

+build.classes.excludes=**/*.java,**/*.form

+# This directory is removed when the project is cleaned:

+build.dir=build

+build.generated.dir=${build.dir}/generated

+build.generated.sources.dir=${build.dir}/generated-sources

+# Only compile against the classpath explicitly listed here:

+build.sysclasspath=ignore

+build.test.classes.dir=${build.dir}/test/classes

+build.test.results.dir=${build.dir}/test/results

+# Uncomment to specify the preferred debugger connection transport:

+#debug.transport=dt_socket

+debug.classpath=\

+    ${run.classpath}

+debug.test.classpath=\

+    ${run.test.classpath}

+# This directory is removed when the project is cleaned:

+dist.dir=dist

+dist.jar=${dist.dir}/Prettify.jar

+dist.javadoc.dir=${dist.dir}/javadoc

+excludes=

+includes=**

+jar.compress=false

+javac.classpath=

+# Space-separated list of extra javac options

+javac.compilerargs=

+javac.deprecation=false

+javac.processorpath=\

+    ${javac.classpath}

+javac.source=1.6

+javac.target=1.6

+javac.test.classpath=\

+    ${javac.classpath}:\

+    ${build.classes.dir}

+javac.test.processorpath=\

+    ${javac.test.classpath}

+javadoc.additionalparam=

+javadoc.author=false

+javadoc.encoding=${source.encoding}

+javadoc.noindex=false

+javadoc.nonavbar=false

+javadoc.notree=false

+javadoc.private=false

+javadoc.splitindex=true

+javadoc.use=true

+javadoc.version=false

+javadoc.windowtitle=

+main.class=

+manifest.file=manifest.mf

+meta.inf.dir=${src.dir}/META-INF

+mkdist.disabled=false

+platform.active=default_platform

+run.classpath=\

+    ${javac.classpath}:\

+    ${build.classes.dir}

+# Space-separated list of JVM arguments used when running the project

+# (you may also define separate properties like run-sys-prop.name=value instead of -Dname=value

+# or test-sys-prop.name=value to set system properties for unit tests):

+run.jvmargs=

+run.test.classpath=\

+    ${javac.test.classpath}:\

+    ${build.test.classes.dir}

+source.encoding=UTF-8

+src.dir=src

+test.src.dir=test

diff --git a/nbproject/project.xml b/nbproject/project.xml
new file mode 100644
index 0000000..80e5298
--- /dev/null
+++ b/nbproject/project.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>

+<project xmlns="http://www.netbeans.org/ns/project/1">

+    <type>org.netbeans.modules.java.j2seproject</type>

+    <configuration>

+        <data xmlns="http://www.netbeans.org/ns/j2se-project/3">

+            <name>Prettify</name>

+            <source-roots>

+                <root id="src.dir"/>

+            </source-roots>

+            <test-roots>

+                <root id="test.src.dir"/>

+            </test-roots>

+        </data>

+    </configuration>

+</project>

diff --git a/src/prettify/CombinePrefixPattern.java b/src/prettify/CombinePrefixPattern.java
new file mode 100644
index 0000000..d9348d3
--- /dev/null
+++ b/src/prettify/CombinePrefixPattern.java
@@ -0,0 +1,289 @@
+// Copyright (C) 2006 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+package prettify;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class CombinePrefixPattern {
+
+    protected int capturedGroupIndex = 0;
+    protected boolean needToFoldCase = false;
+
+    public CombinePrefixPattern() {
+    }
+
+    /**
+     * Given a group of {@link java.util.regex.Pattern}s, returns a {@code RegExp} that globally
+     * matches the union of the sets of strings matched by the input RegExp.
+     * Since it matches globally, if the input strings have a start-of-input
+     * anchor (/^.../), it is ignored for the purposes of unioning.
+     * @param regexs non multiline, non-global regexs.
+     * @return Pattern a global regex.
+     */
+    public Pattern combinePrefixPattern(List<Pattern> regexs) throws Exception {
+        boolean ignoreCase = false;
+
+        for (int i = 0, n = regexs.size(); i < n; ++i) {
+            Pattern regex = regexs.get(i);
+            if ((regex.flags() & Pattern.CASE_INSENSITIVE) != 0) {
+                ignoreCase = true;
+            } else if (regex.pattern().replaceAll("(?i)\\\\u[0-9a-f]{4}|\\\\x[0-9a-f]{2}|\\\\[^ux]", "").matches("(?i)[a-z]")) {
+                needToFoldCase = true;
+                ignoreCase = false;
+                break;
+            }
+        }
+
+        List<String> rewritten = new ArrayList<String>();
+        for (int i = 0, n = regexs.size(); i < n; ++i) {
+            Pattern regex = regexs.get(i);
+            if ((regex.flags() & Pattern.MULTILINE) != 0) {
+                throw new Exception(regex.pattern());
+            }
+            rewritten.add("(?:" + allowAnywhereFoldCaseAndRenumberGroups(regex) + ")");
+        }
+
+        return ignoreCase ? Pattern.compile(Util.join(rewritten, "|"), Pattern.CASE_INSENSITIVE) : Pattern.compile(Util.join(rewritten, "|"));
+    }
+    protected static final Map<Character, Integer> escapeCharToCodeUnit = new HashMap<Character, Integer>();
+
+    static {
+        escapeCharToCodeUnit.put('b', 8);
+        escapeCharToCodeUnit.put('t', 9);
+        escapeCharToCodeUnit.put('n', 0xa);
+        escapeCharToCodeUnit.put('v', 0xb);
+        escapeCharToCodeUnit.put('f', 0xc);
+        escapeCharToCodeUnit.put('r', 0xf);
+    }
+
+    public static int decodeEscape(String charsetPart) {
+        Integer cc0 = charsetPart.codePointAt(0);
+        if (cc0 != 92 /* \\ */) {
+            return cc0;
+        }
+        char c1 = charsetPart.charAt(1);
+        cc0 = escapeCharToCodeUnit.get(c1);
+        if (cc0 != null) {
+            return cc0;
+        } else if ('0' <= c1 && c1 <= '7') {
+            return Integer.parseInt(charsetPart.substring(1), 8);
+        } else if (c1 == 'u' || c1 == 'x') {
+            return Integer.parseInt(charsetPart.substring(2), 16);
+        } else {
+            return charsetPart.codePointAt(1);
+        }
+    }
+
+    public static String encodeEscape(int charCode) {
+        if (charCode < 0x20) {
+            return (charCode < 0x10 ? "\\x0" : "\\x") + Integer.toString(charCode, 16);
+        }
+
+        String ch = new String(Character.toChars(charCode));
+        return (charCode == '\\' || charCode == '-' || charCode == ']' || charCode == '^')
+                ? "\\" + ch : ch;
+    }
+
+    public static String caseFoldCharset(String charSet) {
+        String[] charsetParts = Util.match(Pattern.compile("\\\\u[0-9A-Fa-f]{4}"
+                + "|\\\\x[0-9A-Fa-f]{2}"
+                + "|\\\\[0-3][0-7]{0,2}"
+                + "|\\\\[0-7]{1,2}"
+                + "|\\\\[\\s\\S]"
+                + "|-"
+                + "|[^-\\\\]"), charSet.substring(1, charSet.length() - 1));
+        List<List<Integer>> ranges = new ArrayList<List<Integer>>();
+        boolean inverse = charsetParts[0] != null && charsetParts[0].equals("^");
+
+        List<String> out = new ArrayList<String>(Arrays.asList(new String[]{"["}));
+        if (inverse) {
+            out.add("^");
+        }
+
+        for (int i = inverse ? 1 : 0, n = charsetParts.length; i < n; ++i) {
+            String p = charsetParts[i];
+            if (p.matches("(?i)\\\\[bdsw]")) {  // Don't muck with named groups.
+                out.add(p);
+            } else {
+                int start = decodeEscape(p);
+                int end;
+                if (i + 2 < n && "-".equals(charsetParts[i + 1])) {
+                    end = decodeEscape(charsetParts[i + 2]);
+                    i += 2;
+                } else {
+                    end = start;
+                }
+                ranges.add(Arrays.asList(new Integer[]{start, end}));
+                // If the range might intersect letters, then expand it.
+                // This case handling is too simplistic.
+                // It does not deal with non-latin case folding.
+                // It works for latin source code identifiers though.
+                if (!(end < 65 || start > 122)) {
+                    if (!(end < 65 || start > 90)) {
+                        ranges.add(Arrays.asList(new Integer[]{Math.max(65, start) | 32, Math.min(end, 90) | 32}));
+                    }
+                    if (!(end < 97 || start > 122)) {
+                        ranges.add(Arrays.asList(new Integer[]{Math.max(97, start) & ~32, Math.min(end, 122) & ~32}));
+                    }
+                }
+            }
+        }
+
+        // [[1, 10], [3, 4], [8, 12], [14, 14], [16, 16], [17, 17]]
+        // -> [[1, 12], [14, 14], [16, 17]]
+        Collections.sort(ranges, new Comparator<List<Integer>>() {
+
+            @Override
+            public int compare(List<Integer> a, List<Integer> b) {
+                return a.get(0) != b.get(0) ? (a.get(0) - b.get(0)) : (b.get(1) - a.get(1));
+            }
+        });
+        List<List<Integer>> consolidatedRanges = new ArrayList<List<Integer>>();
+        Map<Integer, Integer> lastRange = new HashMap<Integer, Integer>();
+        for (int i = 0; i < ranges.size(); ++i) {
+            List<Integer> range = ranges.get(i);
+            if (lastRange.get(1) != null && range.get(0) <= lastRange.get(1) + 1) {
+                lastRange.put(1, Math.max(lastRange.get(1), range.get(1)));
+            } else {
+                consolidatedRanges.add(range);
+                lastRange.put(0, range.get(0));
+                lastRange.put(1, range.get(1));
+            }
+        }
+
+        for (int i = 0; i < consolidatedRanges.size(); ++i) {
+            List<Integer> range = consolidatedRanges.get(i);
+            out.add(encodeEscape((int) range.get(0)));
+            if (range.get(1) > range.get(0)) {
+                if (range.get(1) + 1 > range.get(0)) {
+                    out.add("-");
+                }
+                out.add(encodeEscape((int) range.get(1)));
+            }
+        }
+        out.add("]");
+
+        return Util.join(out);
+    }
+
+    public String allowAnywhereFoldCaseAndRenumberGroups(Pattern regex) {
+        // Split into character sets, escape sequences, punctuation strings
+        // like ('(', '(?:', ')', '^'), and runs of characters that do not
+        // include any of the above.
+        String[] parts = Util.match(Pattern.compile("(?:"
+                + "\\[(?:[^\\x5C\\x5D]|\\\\[\\s\\S])*\\]" // a character set
+                + "|\\\\u[A-Fa-f0-9]{4}" // a unicode escape
+                + "|\\\\x[A-Fa-f0-9]{2}" // a hex escape
+                + "|\\\\[0-9]+" // a back-reference or octal escape
+                + "|\\\\[^ux0-9]" // other escape sequence
+                + "|\\(\\?[:!=]" // start of a non-capturing group
+                + "|[\\(\\)\\^]" // start/end of a group, or line start
+                + "|[^\\x5B\\x5C\\(\\)\\^]+" // run of other characters
+                + ")"), regex.pattern());
+        int n = parts.length;
+
+        // Maps captured group numbers to the number they will occupy in
+        // the output or to -1 if that has not been determined, or to
+        // undefined if they need not be capturing in the output.
+        Map<Integer, Integer> capturedGroups = new HashMap<Integer, Integer>();
+
+        // Walk over and identify back references to build the capturedGroups
+        // mapping.
+        for (int i = 0, groupIndex = 0; i < n; ++i) {
+            String p = parts[i];
+            if (p.equals("(")) {
+                // groups are 1-indexed, so max group index is count of '('
+                ++groupIndex;
+            } else if ('\\' == p.charAt(0)) {
+                try {
+                    int decimalValue = Math.abs(Integer.parseInt(p.substring(1)));
+                    if (decimalValue <= groupIndex) {
+                        capturedGroups.put(decimalValue, -1);
+                    } else {
+                        // Replace with an unambiguous escape sequence so that
+                        // an octal escape sequence does not turn into a backreference
+                        // to a capturing group from an earlier regex.
+                        parts[i] = encodeEscape(decimalValue);
+                    }
+                } catch (NumberFormatException ex) {
+                }
+            }
+        }
+
+        // Renumber groups and reduce capturing groups to non-capturing groups
+        // where possible.
+        for (int i : capturedGroups.keySet()) {
+            if (-1 == capturedGroups.get(i)) {
+                capturedGroups.put(i, ++capturedGroupIndex);
+            }
+        }
+        for (int i = 0, groupIndex = 0; i < n; ++i) {
+            String p = parts[i];
+            if (p.equals("(")) {
+                ++groupIndex;
+                if (capturedGroups.get(groupIndex) == null) {
+                    parts[i] = "(?:";
+                }
+            } else if ('\\' == p.charAt(0)) {
+                try {
+                    int decimalValue = Math.abs(Integer.parseInt(p.substring(1)));
+                    if (decimalValue <= groupIndex) {
+                        parts[i] = "\\" + capturedGroups.get(decimalValue);
+                    }
+                } catch (NumberFormatException ex) {
+                }
+            }
+        }
+
+        // Remove any prefix anchors so that the output will match anywhere.
+        // ^^ really does mean an anchored match though.
+        for (int i = 0; i < n; ++i) {
+            if ("^".equals(parts[i]) && !"^".equals(parts[i + 1])) {
+                parts[i] = "";
+            }
+        }
+
+        // Expand letters to groups to handle mixing of case-sensitive and
+        // case-insensitive patterns if necessary.
+        if ((regex.flags() & Pattern.CASE_INSENSITIVE) != 0 && needToFoldCase) {
+            for (int i = 0; i < n; ++i) {
+                String p = parts[i];
+                char ch0 = p.charAt(0);
+                if (p.length() >= 2 && ch0 == '[') {
+                    parts[i] = caseFoldCharset(p);
+                } else if (ch0 == '\\') {
+                    // TODO: handle letters in numeric escapes.
+                    StringBuffer sb = new StringBuffer();
+                    Matcher _matcher = Pattern.compile("[a-zA-Z]").matcher(p);
+                    while (_matcher.find()) {
+                        int cc = _matcher.group(0).codePointAt(0);
+                        _matcher.appendReplacement(sb, "[" + Character.toString((char) (cc & ~32)) + Character.toString((char) (cc | 32)) + "]");
+                    }
+                    _matcher.appendTail(sb);
+                    parts[i] = sb.toString();
+                }
+            }
+        }
+
+        return Util.join(parts);
+    }
+}
diff --git a/src/prettify/JTextComponentRowHeader.java b/src/prettify/JTextComponentRowHeader.java
new file mode 100644
index 0000000..1f98259
--- /dev/null
+++ b/src/prettify/JTextComponentRowHeader.java
@@ -0,0 +1,515 @@
+/**
+ * This is part of the Java SyntaxHighlighter.
+ * 
+ * It is distributed under MIT license. See the file 'readme.txt' for
+ * information on usage and redistribution of this file, and for a
+ * DISCLAIMER OF ALL WARRANTIES.
+ * 
+ * @author Chan Wai Shing <cws1989@gmail.com>
+ */
+package prettify;
+
+import java.awt.Color;
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.Point;
+import java.awt.RenderingHints;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JViewport;
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.DocumentListener;
+import javax.swing.text.BadLocationException;
+import javax.swing.text.Document;
+import javax.swing.text.Element;
+import javax.swing.text.JTextComponent;
+
+/**
+ * A row header panel for JScrollPane.
+ * It is used with JTextComponent for line number displaying.<br />
+ * Currently it only accept fixed-height line.<br />
+ * <b>The usage is not limited to this syntax highlighter, it can be used on all JTextComponent.</b>
+ * @author Chan Wai Shing <cws1989@gmail.com>
+ */
+public class JTextComponentRowHeader extends JPanel {
+
+    /**
+     * Indicate whether it is in debug mode or not.
+     */
+    protected final static boolean debug;
+
+    static {
+        String debugMode = System.getProperty("SyntaxHighlighterDebugMode");
+        debug = debugMode == null || !debugMode.equals("true") ? false : true;
+    }
+    private static final long serialVersionUID = 1L;
+    /**
+     * The anti-aliasing setting of the line number text. See {@link java.awt.RenderingHints}.
+     */
+    private Object textAntiAliasing = RenderingHints.VALUE_TEXT_ANTIALIAS_DEFAULT;
+    /**
+     * The color of the border that joint the gutter and the script text panel.
+     */
+    private Color borderColor = new Color(184, 184, 184);
+    /**
+     * The background of the row when it is highlighted.
+     */
+    private Color highlightedColor = Color.black;
+    /**
+     * The minimum padding from 'the leftmost of the line number text' to 'the left margin'.
+     */
+    private int paddingLeft = 7;
+    /**
+     * The minimum padding from 'the rightmost of the line number text' to 'the right margin' (not to the gutter border).
+     */
+    private int paddingRight = 2;
+    /**
+     * The width of the border that joint the gutter and the script text panel.
+     */
+    private int borderWidth = 1;
+    /**
+     * The JScrollPane that it be added into.
+     */
+    protected JScrollPane scrollPane;
+    /**
+     * The text component to listen the change events on.
+     */
+    protected JTextComponent textComponent;
+    /**
+     * The document of the text component.
+     */
+    protected Document document;
+    /**
+     * The document listener for {@link #document}.
+     */
+    protected DocumentListener documentListener;
+    /**
+     * The cached panel width.
+     */
+    protected int panelWidth;
+    /**
+     * The cached largest row number (for determine panel width {@link #panelWidth}).
+     */
+    protected int largestRowNumber;
+    /**
+     * The cached text component height, for determine panel height.
+     */
+    protected int textComponentHeight;
+    /**
+     * The line number offset. E.g. set offset to 9 will make the first line number to appear at line 1 + 9 = 10
+     */
+    private int lineNumberOffset;
+    /**
+     * The list of line numbers that indicate which lines are needed to be highlighted.
+     */
+    private final List<Integer> highlightedLineList;
+    /**
+     * Indicator indicate whether it is listening to the document change events or not.
+     */
+    private boolean listenToDocumentUpdate;
+
+    /**
+     * Constructor.
+     * @param scrollPane the JScrollPane that it be added into
+     * @param textComponent the text component to listen the change events on
+     */
+    public JTextComponentRowHeader(JScrollPane scrollPane, JTextComponent textComponent) {
+        super();
+
+        if (scrollPane == null) {
+            throw new NullPointerException("argument 'scrollPane' cannot be null");
+        }
+        if (textComponent == null) {
+            throw new NullPointerException("argument 'textComponent' cannot be null");
+        }
+
+        setFont(new Font("Verdana", Font.PLAIN, 10));
+        setForeground(Color.black);
+        setBackground(new Color(233, 232, 226));
+
+        this.scrollPane = scrollPane;
+        this.textComponent = textComponent;
+
+        panelWidth = 0;
+        largestRowNumber = 1;
+        textComponentHeight = 0;
+
+        lineNumberOffset = 0;
+        highlightedLineList = Collections.synchronizedList(new ArrayList<Integer>());
+
+        listenToDocumentUpdate = true;
+
+        document = textComponent.getDocument();
+        documentListener = new DocumentListener() {
+
+            @Override
+            public void insertUpdate(DocumentEvent e) {
+                handleEvent(e);
+            }
+
+            @Override
+            public void removeUpdate(DocumentEvent e) {
+                handleEvent(e);
+            }
+
+            @Override
+            public void changedUpdate(DocumentEvent e) {
+                handleEvent(e);
+            }
+
+            public void handleEvent(DocumentEvent e) {
+                if (!listenToDocumentUpdate) {
+                    return;
+                }
+                Document _document = e.getDocument();
+                if (document == _document) {
+                    checkPanelSize();
+                } else {
+                    _document.removeDocumentListener(this);
+                }
+            }
+        };
+
+        document.addDocumentListener(documentListener);
+
+        checkPanelSize();
+    }
+
+    /**
+     * Check if the 'document of the textComponent' has changed to another document or not.
+     */
+    protected void validateTextComponentDocument() {
+        Document _currentDocument = textComponent.getDocument();
+        if (document != _currentDocument) {
+            document.removeDocumentListener(documentListener);
+            document = _currentDocument;
+            _currentDocument.addDocumentListener(documentListener);
+        }
+    }
+
+    /**
+     * Check whether the height of the row header panel match with the height of the text component or not.
+     * If not, it will invoke {@link #updatePanelSize()}.
+     */
+    protected void checkPanelSize() {
+        validateTextComponentDocument();
+        int _largestRowNumber = document.getDefaultRootElement().getElementCount() + lineNumberOffset;
+        int _panelWidth = getFontMetrics(getFont()).stringWidth(Integer.toString(_largestRowNumber)) + paddingLeft + paddingRight;
+        if (panelWidth != _panelWidth || largestRowNumber != _largestRowNumber) {
+            panelWidth = _panelWidth;
+            largestRowNumber = _largestRowNumber;
+            updatePanelSize();
+        }
+    }
+
+    /**
+     * Update the panel size.
+     */
+    protected void updatePanelSize() {
+        Container parent = getParent();
+        if (parent != null) {
+            parent.doLayout();
+            scrollPane.doLayout();
+            parent.repaint();
+        }
+    }
+
+    /**
+     * The font of the line number.
+     */
+    @Override
+    public void setFont(Font font) {
+        super.setFont(font);
+    }
+
+    /**
+     * The color of the line number.
+     */
+    @Override
+    public void setForeground(Color foreground) {
+        super.setForeground(foreground);
+    }
+
+    /**
+     * The background of the panel.
+     */
+    @Override
+    public void setBackground(Color background) {
+        super.setBackground(background);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public Dimension getPreferredSize() {
+        textComponentHeight = textComponent.getPreferredSize().height;
+        return new Dimension(panelWidth, textComponentHeight);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void paint(Graphics g) {
+        super.paint(g);
+
+        // check whether the height of this panel matches the height of the text component or not
+        Dimension textComponentPreferredSize = textComponent.getPreferredSize();
+        if (textComponentHeight != textComponentPreferredSize.height) {
+            textComponentHeight = textComponentPreferredSize.height;
+            updatePanelSize();
+        }
+
+        JViewport viewport = scrollPane.getViewport();
+        Point viewPosition = viewport.getViewPosition();
+        Dimension viewportSize = viewport.getSize();
+
+        validateTextComponentDocument();
+        Element defaultRootElement = document.getDefaultRootElement();
+
+
+        // maybe able to get the value when font changed and cache them
+        // however i'm not sure if there is any condition which will make the java.awt.FontMetrics get by getFontMetrics() from java.awt.Graphics is different from getFontMetrics() from java.awt.Component
+        FontMetrics fontMetrics = g.getFontMetrics(getFont());
+        int fontHeight = fontMetrics.getHeight();
+        int fontAscent = fontMetrics.getAscent();
+        int fontLeading = fontMetrics.getLeading();
+
+        FontMetrics textPaneFontMetrics = g.getFontMetrics(textComponent.getFont());
+        int textPaneFontHeight = textPaneFontMetrics.getHeight();
+
+
+        // get the location of the document of the left top and right bottom point of the visible part of the text component
+        int documentOffsetStart = textComponent.viewToModel(viewPosition);
+        int documentOffsetEnd = textComponent.viewToModel(new Point(viewPosition.x + viewportSize.width, viewPosition.y + viewportSize.height));
+
+        // convert the location to line number
+        int startLine = defaultRootElement.getElementIndex(documentOffsetStart) + 1 + lineNumberOffset;
+        int endLine = defaultRootElement.getElementIndex(documentOffsetEnd) + 1 + lineNumberOffset;
+
+
+        // draw right border
+        g.setColor(borderColor);
+        g.fillRect(panelWidth - borderWidth, viewPosition.y, borderWidth, viewportSize.height);
+
+        // draw line number
+        int startY = -1, baselineOffset = -1;
+        try {
+            startY = textComponent.modelToView(documentOffsetStart).y;
+            baselineOffset = (textPaneFontHeight / 2) + fontAscent - (fontHeight / 2) + fontLeading;
+        } catch (BadLocationException ex) {
+            if (debug) {
+                Logger.getLogger(JTextComponentRowHeader.class.getName()).log(Level.WARNING, null, ex);
+            }
+            return;
+        }
+
+        // text anti-aliasing
+        ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, textAntiAliasing);
+        // preserve the foreground color (for recover the color after highlighing the line)
+        Color foregroundColor = getForeground();
+
+        g.setColor(foregroundColor);
+        g.setFont(getFont());
+
+        for (int i = startLine, y = startY + baselineOffset; i <= endLine; y += textPaneFontHeight, i++) {
+            boolean highlighted = false;
+            if (highlightedLineList.indexOf((Integer) i) != -1) {
+                // highlight this line
+                g.setColor(borderColor);
+                g.fillRect(0, y - baselineOffset, panelWidth - borderWidth, textPaneFontHeight);
+                g.setColor(highlightedColor);
+                highlighted = true;
+            }
+
+            // draw the line number
+            String lineNumberString = Integer.toString(i);
+            int lineNumberStringWidth = fontMetrics.stringWidth(lineNumberString);
+            g.drawString(lineNumberString, panelWidth - lineNumberStringWidth - paddingRight, y);
+
+            // restore the line number text color
+            if (highlighted) {
+                g.setColor(foregroundColor);
+            }
+        }
+    }
+
+    /**
+     * The anti-aliasing setting of the line number text. See {@link java.awt.RenderingHints}.
+     */
+    public Object getTextAntiAliasing() {
+        return textAntiAliasing;
+    }
+
+    /**
+     * The anti-aliasing setting of the line number text. See {@link java.awt.RenderingHints}.
+     */
+    public void setTextAntiAliasing(Object textAntiAliasing) {
+        if (textAntiAliasing == null) {
+            throw new NullPointerException("argument 'textAntiAliasing' cannot be null");
+        }
+        this.textAntiAliasing = textAntiAliasing;
+        repaint();
+    }
+
+    /**
+     * The color of the border that joint the gutter and the script text panel.
+     */
+    public Color getBorderColor() {
+        return borderColor;
+    }
+
+    /**
+     * The color of the border that joint the gutter and the script text panel.
+     */
+    public void setBorderColor(Color borderColor) {
+        if (borderColor == null) {
+            throw new NullPointerException("argument 'borderColor' cannot be null");
+        }
+        this.borderColor = borderColor;
+        repaint();
+    }
+
+    /**
+     * The background of the highlighted row.
+     */
+    public Color getHighlightedColor() {
+        return highlightedColor;
+    }
+
+    /**
+     * The background of the highlighted row.
+     */
+    public void setHighlightedColor(Color highlightedColor) {
+        if (highlightedColor == null) {
+            throw new NullPointerException("argument 'highlightedColor' cannot be null");
+        }
+        this.highlightedColor = highlightedColor;
+        repaint();
+    }
+
+    /**
+     * The minimum padding from the 'leftmost of the line number text' to the 'left margin'.
+     */
+    public int getPaddingLeft() {
+        return paddingLeft;
+    }
+
+    /**
+     * The minimum padding from 'the leftmost of the line number text' to the 'left margin'.
+     */
+    public void setPaddingLeft(int paddingLeft) {
+        this.paddingLeft = paddingLeft;
+        checkPanelSize();
+    }
+
+    /**
+     * The minimum padding from the 'rightmost of the line number text' to the 'right margin' (not to the gutter border).
+     */
+    public int getPaddingRight() {
+        return paddingRight;
+    }
+
+    /**
+     * The minimum padding from the 'rightmost of the line number text' to the 'right margin' (not to the gutter border).
+     */
+    public void setPaddingRight(int paddingRight) {
+        this.paddingRight = paddingRight;
+        checkPanelSize();
+    }
+
+    /**
+     * The width of the border that joint the gutter and the script text panel.
+     */
+    public int getBorderWidth() {
+        return borderWidth;
+    }
+
+    /**
+     * The width of the border that joint the gutter and the script text panel.
+     */
+    public void setBorderWidth(int borderWidth) {
+        this.borderWidth = borderWidth;
+        repaint();
+    }
+
+    /**
+     * Get the line number offset
+     * @return the offset
+     */
+    public int getLineNumberOffset() {
+        return lineNumberOffset;
+    }
+
+    /**
+     * Set the line number offset. E.g. set offset to 9 will make the first line number to appear at line 1 + 9 = 10
+     * @param offset the offset
+     */
+    public void setLineNumberOffset(int offset) {
+        lineNumberOffset = Math.max(lineNumberOffset, offset);
+        checkPanelSize();
+        repaint();
+    }
+
+    /**
+     * Get the list of highlighted lines.
+     * @return a copy of the list
+     */
+    public List<Integer> getHighlightedLineList() {
+        List<Integer> returnList;
+        synchronized (highlightedLineList) {
+            returnList = new ArrayList<Integer>(highlightedLineList);
+        }
+        return returnList;
+    }
+
+    /**
+     * Set highlighted lines. Note that this will clear all previous recorded highlighted lines.
+     * @param highlightedLineList the list that contain the highlighted lines
+     */
+    public void setHighlightedLineList(List<Integer> highlightedLineList) {
+        synchronized (this.highlightedLineList) {
+            this.highlightedLineList.clear();
+            if (highlightedLineList != null) {
+                this.highlightedLineList.addAll(highlightedLineList);
+            }
+        }
+        repaint();
+    }
+
+    /**
+     * Add highlighted line.
+     * @param lineNumber the line number to highlight
+     */
+    public void addHighlightedLine(int lineNumber) {
+        highlightedLineList.add(lineNumber);
+        repaint();
+    }
+
+    /**
+     * Check if it is listening to the document change events.
+     * @return true if it is listening, false if not 
+     */
+    public boolean isListenToDocumentUpdate() {
+        return listenToDocumentUpdate;
+    }
+
+    /**
+     * Set to listen to document change events or not. It is useful when a number of updates are needed to be done to the text component.
+     * May invoke {@link #updatePanelSize()}.
+     * @param listenToDocumentUpdate true to listen on document change, false not
+     */
+    public void setListenToDocumentUpdate(boolean listenToDocumentUpdate) {
+        this.listenToDocumentUpdate = listenToDocumentUpdate;
+    }
+}
diff --git a/src/prettify/Job.java b/src/prettify/Job.java
new file mode 100644
index 0000000..cc3d37f
--- /dev/null
+++ b/src/prettify/Job.java
@@ -0,0 +1,56 @@
+// Copyright (C) 2006 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+package prettify;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class Job {
+
+    protected int basePos;
+    protected String sourceCode;
+    protected List<Object> decorations;
+
+    public Job() {
+        decorations = new ArrayList<Object>();
+    }
+
+    public int getBasePos() {
+        return basePos;
+    }
+
+    public void setBasePos(int basePos) {
+        this.basePos = basePos;
+    }
+
+    public String getSourceCode() {
+        return sourceCode;
+    }
+
+    public void setSourceCode(String sourceCode) {
+        this.sourceCode = sourceCode;
+    }
+
+    public List<Object> getDecorations() {
+        return new ArrayList<Object>(decorations);
+    }
+
+    public void setDecorations(List<Object> decorations) {
+        if (decorations == null) {
+            this.decorations = new ArrayList<Object>();
+            return;
+        }
+        this.decorations = new ArrayList<Object>(decorations);
+    }
+}
diff --git a/src/prettify/Prettify.java b/src/prettify/Prettify.java
new file mode 100644
index 0000000..5e50f7a
--- /dev/null
+++ b/src/prettify/Prettify.java
@@ -0,0 +1,703 @@
+// Copyright (C) 2006 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+package prettify;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.regex.Pattern;
+
+/**
+ * @fileoverview
+ * some functions for browser-side pretty printing of code contained in html.
+ *
+ * <p>
+ * For a fairly comprehensive set of languages see the
+ * <a href="http://google-code-prettify.googlecode.com/svn/trunk/README.html#langs">README</a>
+ * file that came with this source.  At a minimum, the lexer should work on a
+ * number of languages including C and friends, Java, Python, Bash, SQL, HTML,
+ * XML, CSS, Javascript, and Makefiles.  It works passably on Ruby, PHP and Awk
+ * and a subset of Perl, but, because of commenting conventions, doesn't work on
+ * Smalltalk, Lisp-like, or CAML-like languages without an explicit lang class.
+ * <p>
+ * Usage: <ol>
+ * <li> include this source file in an html page via
+ *   {@code <script type="text/javascript" src="/path/to/prettify.js"></script>}
+ * <li> define style rules.  See the example page for examples.
+ * <li> mark the {@code <pre>} and {@code <code>} tags in your source with
+ *    {@code class=prettyprint.}
+ *    You can also use the (html deprecated) {@code <xmp>} tag, but the pretty
+ *    printer needs to do more substantial DOM manipulations to support that, so
+ *    some css styles may not be preserved.
+ * </ol>
+ * That's it.  I wanted to keep the API as simple as possible, so there's no
+ * need to specify which language the code is in, but if you wish, you can add
+ * another class to the {@code <pre>} or {@code <code>} element to specify the
+ * language, as in {@code <pre class="prettyprint lang-java">}.  Any class that
+ * starts with "lang-" followed by a file extension, specifies the file type.
+ * See the "lang-*.js" files in this directory for code that implements
+ * per-language file handlers.
+ * <p>
+ * Change log:<br>
+ * cbeust, 2006/08/22
+ * <blockquote>
+ *   Java annotations (start with "@") are now captured as literals ("lit")
+ * </blockquote>
+ */
+public class Prettify {
+
+    // Keyword lists for various languages.
+    public static final String FLOW_CONTROL_KEYWORDS = "break,continue,do,else,for,if,return,while";
+    public static final String C_KEYWORDS = FLOW_CONTROL_KEYWORDS + "," + "auto,case,char,const,default,"
+            + "double,enum,extern,float,goto,int,long,register,short,signed,sizeof,"
+            + "static,struct,switch,typedef,union,unsigned,void,volatile";
+    public static final String COMMON_KEYWORDS = C_KEYWORDS + "," + "catch,class,delete,false,import,"
+            + "new,operator,private,protected,public,this,throw,true,try,typeof";
+    public static final String CPP_KEYWORDS = COMMON_KEYWORDS + "," + "alignof,align_union,asm,axiom,bool,"
+            + "concept,concept_map,const_cast,constexpr,decltype,"
+            + "dynamic_cast,explicit,export,friend,inline,late_check,"
+            + "mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,"
+            + "template,typeid,typename,using,virtual,where";
+    public static final String JAVA_KEYWORDS = COMMON_KEYWORDS + ","
+            + "abstract,boolean,byte,extends,final,finally,implements,import,"
+            + "instanceof,null,native,package,strictfp,super,synchronized,throws,"
+            + "transient";
+    public static final String CSHARP_KEYWORDS = JAVA_KEYWORDS + ","
+            + "as,base,by,checked,decimal,delegate,descending,dynamic,event,"
+            + "fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,"
+            + "object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,"
+            + "stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var";
+    public static final String COFFEE_KEYWORDS = "all,and,by,catch,class,else,extends,false,finally,"
+            + "for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,"
+            + "true,try,unless,until,when,while,yes";
+    public static final String JSCRIPT_KEYWORDS = COMMON_KEYWORDS + ","
+            + "debugger,eval,export,function,get,null,set,undefined,var,with,"
+            + "Infinity,NaN";
+    public static final String PERL_KEYWORDS = "caller,delete,die,do,dump,elsif,eval,exit,foreach,for,"
+            + "goto,if,import,last,local,my,next,no,our,print,package,redo,require,"
+            + "sub,undef,unless,until,use,wantarray,while,BEGIN,END";
+    public static final String PYTHON_KEYWORDS = FLOW_CONTROL_KEYWORDS + "," + "and,as,assert,class,def,del,"
+            + "elif,except,exec,finally,from,global,import,in,is,lambda,"
+            + "nonlocal,not,or,pass,print,raise,try,with,yield,"
+            + "False,True,None";
+    public static final String RUBY_KEYWORDS = FLOW_CONTROL_KEYWORDS + "," + "alias,and,begin,case,class,"
+            + "def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,"
+            + "rescue,retry,self,super,then,true,undef,unless,until,when,yield,"
+            + "BEGIN,END";
+    public static final String SH_KEYWORDS = FLOW_CONTROL_KEYWORDS + "," + "case,done,elif,esac,eval,fi,"
+            + "function,in,local,set,then,until";
+    public static final String ALL_KEYWORDS = CPP_KEYWORDS + "," + CSHARP_KEYWORDS + "," + JSCRIPT_KEYWORDS + "," + PERL_KEYWORDS + ","
+            + PYTHON_KEYWORDS + "," + RUBY_KEYWORDS + "," + SH_KEYWORDS;
+    public static final Pattern C_TYPES = Pattern.compile("^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\\d*)");
+    // token style names.  correspond to css classes
+    /**
+     * token style for a string literal
+     */
+    public static final String PR_STRING = "str";
+    /**
+     * token style for a keyword
+     */
+    public static final String PR_KEYWORD = "kwd";
+    /**
+     * token style for a comment
+     */
+    public static final String PR_COMMENT = "com";
+    /**
+     * token style for a type
+     */
+    public static final String PR_TYPE = "';";
+    /**
+     * token style for a literal value.  e.g. 1, null, true.
+     */
+    public static final String PR_LITERAL = "lit";
+    /**
+     * token style for a punctuation string.
+     */
+    public static final String PR_PUNCTUATION = "pun";
+    /**
+     * token style for a plain text.
+     */
+    public static final String PR_PLAIN = "pln";
+    /**
+     * token style for an sgml tag.
+     */
+    public static final String PR_TAG = "tag";
+    /**
+     * token style for a markup declaration such as a DOCTYPE.
+     */
+    public static final String PR_DECLARATION = "dec";
+    /**
+     * token style for embedded source.
+     */
+    public static final String PR_SOURCE = "src";
+    /**
+     * token style for an sgml attribute name.
+     */
+    public static final String PR_ATTRIB_NAME = "atn";
+    /**
+     * token style for an sgml attribute value.
+     */
+    public static final String PR_ATTRIB_VALUE = "atv";
+    /**
+     * A class that indicates a section of markup that is not code, e.g. to allow
+     * embedding of line numbers within code listings.
+     */
+    public static final String PR_NOCODE = "nocode";
+    /**
+     * A set of tokens that can precede a regular expression literal in
+     * javascript
+     * http://web.archive.org/web/20070717142515/http://www.mozilla.org/js/language/js20/rationale/syntax.html
+     * has the full list, but I've removed ones that might be problematic when
+     * seen in languages that don't support regular expression literals.
+     *
+     * <p>Specifically, I've removed any keywords that can't precede a regexp
+     * literal in a syntactically legal javascript program, and I've removed the
+     * "in" keyword since it's not a keyword in many languages, and might be used
+     * as a count of inches.
+     *
+     * <p>The link above does not accurately describe EcmaScript rules since
+     * it fails to distinguish between (a=++/b/i) and (a++/b/i) but it works
+     * very well in practice.
+     */
+    private static final String REGEXP_PRECEDER_PATTERN = "(?:^^\\.?|[+-]|[!=]=?=?|\\#|%=?|&&?=?|\\(|\\*=?|[+\\-]=|->|\\/=?|::?|<<?=?|>>?>?=?|,|;|\\?|@|\\[|~|\\{|\\^\\^?=?|\\|\\|?=?|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*";
+    // CAVEAT: this does not properly handle the case where a regular
+    // expression immediately follows another since a regular expression may
+    // have flags for case-sensitivity and the like.  Having regexp tokens
+    // adjacent is not valid in any language I'm aware of, so I'm punting.
+    // TODO: maybe style special characters inside a regexp as punctuation.
+
+    public Prettify() {
+        try {
+            Map<String, Object> decorateSourceMap = new HashMap<String, Object>();
+            decorateSourceMap.put("keywords", ALL_KEYWORDS);
+            decorateSourceMap.put("hashComments", true);
+            decorateSourceMap.put("cStyleComments", true);
+            decorateSourceMap.put("multiLineStrings", true);
+            decorateSourceMap.put("regexLiterals", true);
+            registerLangHandler(sourceDecorator(decorateSourceMap), Arrays.asList(new String[]{"default-code"}));
+
+            List<List<Object>> shortcutStylePatterns = new ArrayList<List<Object>>();
+            List<List<Object>> fallthroughStylePatterns = new ArrayList<List<Object>>();
+            fallthroughStylePatterns.add(Arrays.asList(new Object[]{PR_PLAIN, Pattern.compile("^[^<?]+")}));
+            fallthroughStylePatterns.add(Arrays.asList(new Object[]{PR_DECLARATION, Pattern.compile("^<!\\w[^>]*(?:>|$)")}));
+            fallthroughStylePatterns.add(Arrays.asList(new Object[]{PR_COMMENT, Pattern.compile("^<\\!--[\\s\\S]*?(?:-\\->|$)")}));
+            // Unescaped content in an unknown language
+            fallthroughStylePatterns.add(Arrays.asList(new Object[]{"lang-", Pattern.compile("^<\\?([\\s\\S]+?)(?:\\?>|$)")}));
+            fallthroughStylePatterns.add(Arrays.asList(new Object[]{"lang-", Pattern.compile("^<%([\\s\\S]+?)(?:%>|$)")}));
+            fallthroughStylePatterns.add(Arrays.asList(new Object[]{PR_PUNCTUATION, Pattern.compile("^(?:<[%?]|[%?]>)")}));
+            fallthroughStylePatterns.add(Arrays.asList(new Object[]{"lang-", Pattern.compile("^<xmp\\b[^>]*>([\\s\\S]+?)<\\/xmp\\b[^>]*>", Pattern.CASE_INSENSITIVE)}));
+            // Unescaped content in javascript.  (Or possibly vbscript).
+            fallthroughStylePatterns.add(Arrays.asList(new Object[]{"lang-js", Pattern.compile("^<script\\b[^>]*>([\\s\\S]*?)(<\\/script\\b[^>]*>)", Pattern.CASE_INSENSITIVE)}));
+            // Contains unescaped stylesheet content
+            fallthroughStylePatterns.add(Arrays.asList(new Object[]{"lang-css", Pattern.compile("^<style\\b[^>]*>([\\s\\S]*?)(<\\/style\\b[^>]*>)", Pattern.CASE_INSENSITIVE)}));
+            fallthroughStylePatterns.add(Arrays.asList(new Object[]{"lang-in.tag", Pattern.compile("^(<\\/?[a-z][^<>]*>)", Pattern.CASE_INSENSITIVE)}));
+            registerLangHandler(new CreateSimpleLexer(shortcutStylePatterns, fallthroughStylePatterns), Arrays.asList(new String[]{"default-markup", "htm", "html", "mxml", "xhtml", "xml", "xsl"}));
+
+            shortcutStylePatterns = new ArrayList<List<Object>>();
+            fallthroughStylePatterns = new ArrayList<List<Object>>();
+            shortcutStylePatterns.add(Arrays.asList(new Object[]{PR_PLAIN, Pattern.compile("^[\\s]+"), null, " \t\r\n"}));
+            shortcutStylePatterns.add(Arrays.asList(new Object[]{PR_ATTRIB_VALUE, Pattern.compile("^(?:\\\"[^\\\"]*\\\"?|\\'[^\\']*\\'?)"), null, " \t\r\n"}));
+            fallthroughStylePatterns.add(Arrays.asList(new Object[]{"lang-uq.val", Pattern.compile("^^<\\/?[a-z](?:[\\w.:-]*\\w)?|\\/?>$", Pattern.CASE_INSENSITIVE)}));
+            fallthroughStylePatterns.add(Arrays.asList(new Object[]{PR_PUNCTUATION, Pattern.compile("^[=<>\\/]+")}));
+            fallthroughStylePatterns.add(Arrays.asList(new Object[]{"lang-js", Pattern.compile("^on\\w+\\s*=\\s*\\\"([^\\\"]+)\\\"", Pattern.CASE_INSENSITIVE)}));
+            fallthroughStylePatterns.add(Arrays.asList(new Object[]{"lang-js", Pattern.compile("^on\\w+\\s*=\\s*\\'([^\\']+)\\'", Pattern.CASE_INSENSITIVE)}));
+            fallthroughStylePatterns.add(Arrays.asList(new Object[]{"lang-js", Pattern.compile("^on\\w+\\s*=\\s*([^\\\"\\'>\\s]+)", Pattern.CASE_INSENSITIVE)}));
+            fallthroughStylePatterns.add(Arrays.asList(new Object[]{"lang-css", Pattern.compile("^style\\s*=\\s*\\\"([^\\\"]+)\\\"", Pattern.CASE_INSENSITIVE)}));
+            fallthroughStylePatterns.add(Arrays.asList(new Object[]{"lang-css", Pattern.compile("^style\\s*=\\s*\\'([^\\']+)\\'", Pattern.CASE_INSENSITIVE)}));
+            fallthroughStylePatterns.add(Arrays.asList(new Object[]{"lang-css", Pattern.compile("^style\\s*=\\s\\*([^\\\"\\'>\\s]+)", Pattern.CASE_INSENSITIVE)}));
+            registerLangHandler(new CreateSimpleLexer(shortcutStylePatterns, fallthroughStylePatterns), Arrays.asList(new String[]{"in.tag"}));
+
+            shortcutStylePatterns = new ArrayList<List<Object>>();
+            fallthroughStylePatterns = new ArrayList<List<Object>>();
+            fallthroughStylePatterns.add(Arrays.asList(new Object[]{PR_ATTRIB_VALUE, Pattern.compile("^[\\s\\S]+")}));
+            registerLangHandler(new CreateSimpleLexer(shortcutStylePatterns, fallthroughStylePatterns), Arrays.asList(new String[]{"uq.val"}));
+
+            decorateSourceMap = new HashMap<String, Object>();
+            decorateSourceMap.put("keywords", CPP_KEYWORDS);
+            decorateSourceMap.put("hashComments", true);
+            decorateSourceMap.put("cStyleComments", true);
+            decorateSourceMap.put("types", C_TYPES);
+            registerLangHandler(sourceDecorator(decorateSourceMap), Arrays.asList(new String[]{"c", "cc", "cpp", "cxx", "cyc", "m"}));
+
+            decorateSourceMap = new HashMap<String, Object>();
+            decorateSourceMap.put("keywords", "null,true,false");
+            registerLangHandler(sourceDecorator(decorateSourceMap), Arrays.asList(new String[]{"json"}));
+
+            decorateSourceMap = new HashMap<String, Object>();
+            decorateSourceMap.put("keywords", CSHARP_KEYWORDS);
+            decorateSourceMap.put("hashComments", true);
+            decorateSourceMap.put("cStyleComments", true);
+            decorateSourceMap.put("verbatimStrings", true);
+            decorateSourceMap.put("types", C_TYPES);
+            registerLangHandler(sourceDecorator(decorateSourceMap), Arrays.asList(new String[]{"cs"}));
+
+            decorateSourceMap = new HashMap<String, Object>();
+            decorateSourceMap.put("keywords", JAVA_KEYWORDS);
+            decorateSourceMap.put("cStyleComments", true);
+            registerLangHandler(sourceDecorator(decorateSourceMap), Arrays.asList(new String[]{"java"}));
+
+            decorateSourceMap = new HashMap<String, Object>();
+            decorateSourceMap.put("keywords", SH_KEYWORDS);
+            decorateSourceMap.put("hashComments", true);
+            decorateSourceMap.put("multiLineStrings", true);
+            registerLangHandler(sourceDecorator(decorateSourceMap), Arrays.asList(new String[]{"bsh", "csh", "sh"}));
+
+            decorateSourceMap = new HashMap<String, Object>();
+            decorateSourceMap.put("keywords", PYTHON_KEYWORDS);
+            decorateSourceMap.put("hashComments", true);
+            decorateSourceMap.put("multiLineStrings", true);
+            decorateSourceMap.put("tripleQuotedStrings", true);
+            registerLangHandler(sourceDecorator(decorateSourceMap), Arrays.asList(new String[]{"cv", "py"}));
+
+            decorateSourceMap = new HashMap<String, Object>();
+            decorateSourceMap.put("keywords", PERL_KEYWORDS);
+            decorateSourceMap.put("hashComments", true);
+            decorateSourceMap.put("multiLineStrings", true);
+            decorateSourceMap.put("regexLiterals", true);
+            registerLangHandler(sourceDecorator(decorateSourceMap), Arrays.asList(new String[]{"perl", "pl", "pm"}));
+
+            decorateSourceMap = new HashMap<String, Object>();
+            decorateSourceMap.put("keywords", RUBY_KEYWORDS);
+            decorateSourceMap.put("hashComments", true);
+            decorateSourceMap.put("multiLineStrings", true);
+            decorateSourceMap.put("regexLiterals", true);
+            registerLangHandler(sourceDecorator(decorateSourceMap), Arrays.asList(new String[]{"rb"}));
+
+            decorateSourceMap = new HashMap<String, Object>();
+            decorateSourceMap.put("keywords", JSCRIPT_KEYWORDS);
+            decorateSourceMap.put("cStyleComments", true);
+            decorateSourceMap.put("regexLiterals", true);
+            registerLangHandler(sourceDecorator(decorateSourceMap), Arrays.asList(new String[]{"js"}));
+
+            decorateSourceMap = new HashMap<String, Object>();
+            decorateSourceMap.put("keywords", COFFEE_KEYWORDS);
+            decorateSourceMap.put("hashComments", 3); // ### style block comments
+            decorateSourceMap.put("cStyleComments", true);
+            decorateSourceMap.put("multilineStrings", true);
+            decorateSourceMap.put("tripleQuotedStrings", true);
+            decorateSourceMap.put("regexLiterals", true);
+            registerLangHandler(sourceDecorator(decorateSourceMap), Arrays.asList(new String[]{"coffee"}));
+
+            shortcutStylePatterns = new ArrayList<List<Object>>();
+            fallthroughStylePatterns = new ArrayList<List<Object>>();
+            fallthroughStylePatterns.add(Arrays.asList(new Object[]{PR_STRING, Pattern.compile("^[\\s\\S]+")}));
+            registerLangHandler(new CreateSimpleLexer(shortcutStylePatterns, fallthroughStylePatterns), Arrays.asList(new String[]{"regex"}));
+        } catch (Exception ex) {
+            Logger.getLogger(Prettify.class.getName()).log(Level.SEVERE, null, ex);
+        }
+    }
+
+    /**
+     * Apply the given language handler to sourceCode and add the resulting
+     * decorations to out.
+     * @param basePos the index of sourceCode within the chunk of source
+     *    whose decorations are already present on out.
+     */
+    public static void appendDecorations(int basePos, String sourceCode, CreateSimpleLexer langHandler, List<Object> out) {
+        if (sourceCode == null) {
+            throw new NullPointerException("argument 'sourceCode' cannot be null");
+        }
+        Job job = new Job();
+        job.setSourceCode(sourceCode);
+        job.setBasePos(basePos);
+        langHandler.decorate(job);
+        out.addAll(job.getDecorations());
+    }
+
+    public class CreateSimpleLexer {
+
+        protected List<List<Object>> fallthroughStylePatterns;
+        protected Map<Character, List<Object>> shortcuts = new HashMap<Character, List<Object>>();
+        protected Pattern tokenizer;
+        protected int nPatterns;
+
+        /** Given triples of [style, pattern, context] returns a lexing function,
+         * The lexing function interprets the patterns to find token boundaries and
+         * returns a decoration list of the form
+         * [index_0, style_0, index_1, style_1, ..., index_n, style_n]
+         * where index_n is an index into the sourceCode, and style_n is a style
+         * constant like PR_PLAIN.  index_n-1 <= index_n, and style_n-1 applies to
+         * all characters in sourceCode[index_n-1:index_n].
+         *
+         * The stylePatterns is a list whose elements have the form
+         * [style : string, pattern : RegExp, DEPRECATED, shortcut : string].
+         *
+         * Style is a style constant like PR_PLAIN, or can be a string of the
+         * form 'lang-FOO', where FOO is a language extension describing the
+         * language of the portion of the token in $1 after pattern executes.
+         * E.g., if style is 'lang-lisp', and group 1 contains the text
+         * '(hello (world))', then that portion of the token will be passed to the
+         * registered lisp handler for formatting.
+         * The text before and after group 1 will be restyled using this decorator
+         * so decorators should take care that this doesn't result in infinite
+         * recursion.  For example, the HTML lexer rule for SCRIPT elements looks
+         * something like ['lang-js', /<[s]cript>(.+?)<\/script>/].  This may match
+         * '<script>foo()<\/script>', which would cause the current decorator to
+         * be called with '<script>' which would not match the same rule since
+         * group 1 must not be empty, so it would be instead styled as PR_TAG by
+         * the generic tag rule.  The handler registered for the 'js' extension would
+         * then be called with 'foo()', and finally, the current decorator would
+         * be called with '<\/script>' which would not match the original rule and
+         * so the generic tag rule would identify it as a tag.
+         *
+         * Pattern must only match prefixes, and if it matches a prefix, then that
+         * match is considered a token with the same style.
+         *
+         * Context is applied to the last non-whitespace, non-comment token
+         * recognized.
+         *
+         * Shortcut is an optional string of characters, any of which, if the first
+         * character, gurantee that this pattern and only this pattern matches.
+         *
+         * @param shortcutStylePatterns patterns that always start with
+         *   a known character.  Must have a shortcut string.
+         * @param fallthroughStylePatterns patterns that will be tried in
+         *   order if the shortcut ones fail.  May have shortcuts.
+         */
+        public CreateSimpleLexer(List<List<Object>> shortcutStylePatterns, List<List<Object>> fallthroughStylePatterns) throws Exception {
+            this.fallthroughStylePatterns = fallthroughStylePatterns;
+
+            List<List<Object>> allPatterns = new ArrayList<List<Object>>(shortcutStylePatterns);
+            allPatterns.addAll(fallthroughStylePatterns);
+            List<Pattern> allRegexs = new ArrayList<Pattern>();
+            Map<String, Object> regexKeys = new HashMap<String, Object>();
+            for (int i = 0, n = allPatterns.size(); i < n; ++i) {
+                List<Object> patternParts = allPatterns.get(i);
+                String shortcutChars = patternParts.size() > 4 ? (String) patternParts.get(3) : null;
+                if (shortcutChars != null) {
+                    for (int c = shortcutChars.length(); --c >= 0;) {
+                        shortcuts.put(shortcutChars.charAt(c), patternParts);
+                    }
+                }
+                Pattern regex = (Pattern) patternParts.get(1);
+                String k = regex.pattern();
+                if (regexKeys.get(k) == null) {
+                    allRegexs.add(regex);
+                    regexKeys.put(k, new Object());
+                }
+            }
+            allRegexs.add(Pattern.compile("[\0-\\uffff]"));
+            tokenizer = new CombinePrefixPattern().combinePrefixPattern(allRegexs);
+
+            nPatterns = fallthroughStylePatterns.size();
+        }
+
+        /**
+         * Lexes job.sourceCode and produces an output array job.decorations of
+         * style classes preceded by the position at which they start in
+         * job.sourceCode in order.
+         *
+         * @param job an object like <pre>{
+         *    sourceCode: {string} sourceText plain text,
+         *    basePos: {int} position of job.sourceCode in the larger chunk of
+         *        sourceCode.
+         * }</pre>
+         */
+        public void decorate(Job job) {
+            String sourceCode = job.getSourceCode();
+            int basePos = job.getBasePos();
+            /** Even entries are positions in source in ascending order.  Odd enties
+             * are style markers (e.g., PR_COMMENT) that run from that position until
+             * the end.
+             * @type {Array.<number|string>}
+             */
+            List<Object> decorations = new ArrayList<Object>(Arrays.asList(new Object[]{basePos, PR_PLAIN}));
+            int pos = 0;  // index into sourceCode
+            String[] tokens = Util.match(tokenizer, sourceCode);
+            Map<String, String> styleCache = new HashMap<String, String>();
+
+            for (int ti = 0, nTokens = tokens.length; ti < nTokens; ++ti) {
+                String token = tokens[ti];
+                String style = styleCache.get(token);
+                String[] match = null;
+
+                boolean isEmbedded;
+                if (style != null) {
+                    isEmbedded = false;
+                } else {
+                    List<Object> patternParts = shortcuts.get(token.charAt(0));
+                    if (patternParts != null) {
+                        match = Util.match((Pattern) patternParts.get(1), token);
+                        style = (String) patternParts.get(0);
+                    } else {
+                        for (int i = 0; i < nPatterns; ++i) {
+                            patternParts = fallthroughStylePatterns.get(i);
+                            match = Util.match((Pattern) patternParts.get(1), token);
+                            if (match.length != 0) {
+                                style = (String) patternParts.get(0);
+                                break;
+                            }
+                        }
+
+                        if (match.length == 0) {  // make sure that we make progress
+                            style = PR_PLAIN;
+                        }
+                    }
+
+                    isEmbedded = style != null && style.length() >= 5 && style.startsWith("lang-");
+                    if (isEmbedded && !(match.length > 1)) {
+                        isEmbedded = false;
+                        style = PR_SOURCE;
+                    }
+
+                    if (!isEmbedded) {
+                        styleCache.put(token, style);
+                    }
+                }
+
+                int tokenStart = pos;
+                pos += token.length();
+
+                if (!isEmbedded) {
+                    decorations.add(basePos + tokenStart);
+                    decorations.add(style);
+                } else {  // Treat group 1 as an embedded block of source code.
+                    String embeddedSource = match[1];
+                    int embeddedSourceStart = token.indexOf(embeddedSource);
+                    int embeddedSourceEnd = embeddedSourceStart + embeddedSource.length();
+                    if (match.length > 2) {
+                        // If embeddedSource can be blank, then it would match at the
+                        // beginning which would cause us to infinitely recurse on the
+                        // entire token, so we catch the right context in match[2].
+                        embeddedSourceEnd = token.length() - match[2].length();
+                        embeddedSourceStart = embeddedSourceEnd = embeddedSource.length();
+                    }
+                    String lang = style.substring(5);
+                    // Decorate the left of the embedded source
+                    appendDecorations(basePos + tokenStart,
+                            token.substring(0, embeddedSourceStart),
+                            this, decorations);
+                    // Decorate the embedded source
+                    appendDecorations(basePos + tokenStart + embeddedSourceStart,
+                            embeddedSource,
+                            langHandlerForExtension(lang, embeddedSource),
+                            decorations);
+                    // Decorate the right of the embedded section
+                    appendDecorations(basePos + tokenStart + embeddedSourceEnd,
+                            token.substring(embeddedSourceEnd),
+                            this, decorations);
+                }
+            }
+
+            job.setDecorations(decorations);
+        }
+    }
+
+    /** returns a function that produces a list of decorations from source text.
+     *
+     * This code treats ", ', and ` as string delimiters, and \ as a string
+     * escape.  It does not recognize perl's qq() style strings.
+     * It has no special handling for double delimiter escapes as in basic, or
+     * the tripled delimiters used in python, but should work on those regardless
+     * although in those cases a single string literal may be broken up into
+     * multiple adjacent string literals.
+     *
+     * It recognizes C, C++, and shell style comments.
+     *
+     * @param options a set of optional parameters.
+     * @return a function that examines the source code
+     *     in the input job and builds the decoration list.
+     */
+    public CreateSimpleLexer sourceDecorator(Map<String, Object> options) throws Exception {
+        List<List<Object>> shortcutStylePatterns = new ArrayList<List<Object>>();
+        List<List<Object>> fallthroughStylePatterns = new ArrayList<List<Object>>();
+        if (options.get("tripleQuotedStrings") != null) {
+            // '''multi-line-string''', 'single-line-string', and double-quoted
+            shortcutStylePatterns.add(Arrays.asList(new Object[]{PR_STRING,
+                        Pattern.compile("^(?:\\'\\'\\'(?:[^\\'\\\\]|\\\\[\\s\\S]|\\'{1,2}(?=[^\\']))*(?:\\'\\'\\'|$)|\\\"\\\"\\\"(?:[^\\\"\\\\]|\\\\[\\s\\S]|\\\"{1,2}(?=[^\\\"]))*(?:\\\"\\\"\\\"|$)|\\'(?:[^\\\\\\']|\\\\[\\s\\S])*(?:\\'|$)|\\\"(?:[^\\\\\\\"]|\\\\[\\s\\S])*(?:\\\"|$))"),
+                        null,
+                        "'\""}));
+        } else if (options.get("multiLineStrings") != null) {
+            // 'multi-line-string', "multi-line-string"
+            shortcutStylePatterns.add(Arrays.asList(new Object[]{PR_STRING,
+                        Pattern.compile("^(?:\\'(?:[^\\\\\\']|\\\\[\\s\\S])*(?:\\'|$)|\\\"(?:[^\\\\\\\"]|\\\\[\\s\\S])*(?:\\\"|$)|\\`(?:[^\\\\\\`]|\\\\[\\s\\S])*(?:\\`|$))"),
+                        null,
+                        "'\"`"}));
+        } else {
+            // 'single-line-string', "single-line-string"
+            shortcutStylePatterns.add(Arrays.asList(new Object[]{PR_STRING,
+                        Pattern.compile("^(?:\\'(?:[^\\\\\\'\r\n]|\\\\.)*(?:\\'|$)|\\\"(?:[^\\\\\\\"\r\n]|\\\\.)*(?:\\\"|$))"),
+                        null,
+                        "\"'"}));
+        }
+        if (options.get("verbatinStrings") != null) {
+            // verbatim-string-literal production from the C# grammar.  See issue 93.
+            fallthroughStylePatterns.add(Arrays.asList(new Object[]{PR_STRING,
+                        Pattern.compile("^@\\\"(?:[^\\\"]|\\\"\\\")*(?:\\\"|$)"),
+                        null}));
+        }
+        Object hc = options.get("hashComments");
+        if (hc != null) {
+            if (options.get("cStyleComments") != null) {
+                if ((hc instanceof Integer) && (Integer) hc > 1) {  // multiline hash comments
+                    shortcutStylePatterns.add(Arrays.asList(new Object[]{PR_COMMENT,
+                                Pattern.compile("^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)"),
+                                null,
+                                "#"}));
+                } else {
+                    // Stop C preprocessor declarations at an unclosed open comment
+                    shortcutStylePatterns.add(Arrays.asList(new Object[]{PR_COMMENT,
+                                Pattern.compile("^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\\b|[^\r\n]*)"),
+                                null,
+                                "#"}));
+                }
+                fallthroughStylePatterns.add(Arrays.asList(new Object[]{PR_STRING,
+                            Pattern.compile("^<(?:(?:(?:\\.\\.\\/)*|\\/?)(?:[\\w-]+(?:\\/[\\w-]+)+)?[\\w-]+\\.h|[a-z]\\w*)>"),
+                            null}));
+            } else {
+                shortcutStylePatterns.add(Arrays.asList(new Object[]{PR_COMMENT,
+                            Pattern.compile("^#[^\r\n]*"),
+                            null,
+                            "#"}));
+            }
+        }
+        if (options.get("cStyleComments") != null) {
+            fallthroughStylePatterns.add(Arrays.asList(new Object[]{PR_COMMENT,
+                        Pattern.compile("^\\/\\/[^\r\n]*"),
+                        null}));
+
+            fallthroughStylePatterns.add(Arrays.asList(new Object[]{PR_COMMENT,
+                        Pattern.compile("^\\/\\*[\\s\\S]*?(?:\\*\\/|$)"),
+                        null}));
+        }
+        if (options.get("regexLiterals") != null) {
+            /**
+             * @const
+             */
+            String REGEX_LITERAL =
+                    // A regular expression literal starts with a slash that is
+                    // not followed by * or / so that it is not confused with
+                    // comments.
+                    "/(?=[^/*])"
+                    // and then contains any number of raw characters,
+                    + "(?:[^/\\x5B\\x5C]"
+                    // escape sequences (\x5C),
+                    + "|\\x5C[\\s\\S]"
+                    // or non-nesting character sets (\x5B\x5D);
+                    + "|\\x5B(?:[^\\x5C\\x5D]|\\x5C[\\s\\S])*(?:\\x5D|$))+"
+                    // finally closed by a /.
+                    + "/";
+            fallthroughStylePatterns.add(Arrays.asList(new Object[]{"lang-regex",
+                        Pattern.compile("^" + REGEXP_PRECEDER_PATTERN + "(" + REGEX_LITERAL + ")")}));
+        }
+
+        Pattern types = (Pattern) options.get("types");
+        if (types != null) {
+            fallthroughStylePatterns.add(Arrays.asList(new Object[]{PR_TYPE, types}));
+        }
+
+        if (options.get("keywords") != null) {
+            String keywords = ((String) options.get("keywords")).replaceAll("^ | $", "");
+            if (keywords.length() != 0) {
+                fallthroughStylePatterns.add(Arrays.asList(new Object[]{PR_KEYWORD,
+                            Pattern.compile("^(?:" + keywords.replaceAll("[\\s,]+", "|") + ")\\b"),
+                            null}));
+            }
+        }
+
+        shortcutStylePatterns.add(Arrays.asList(new Object[]{PR_PLAIN,
+                    Pattern.compile("^\\s+"),
+                    null,
+                    " \r\n\t\\xA0"
+                }));
+
+        // TODO(mikesamuel): recognize non-latin letters and numerals in idents
+        fallthroughStylePatterns.add(Arrays.asList(new Object[]{PR_LITERAL,
+                    Pattern.compile("^@[a-z_$][a-z_$@0-9]*", Pattern.CASE_INSENSITIVE),
+                    null}));
+        fallthroughStylePatterns.add(Arrays.asList(new Object[]{PR_TYPE,
+                    Pattern.compile("^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\\w+_t\\b)"),
+                    null}));
+        fallthroughStylePatterns.add(Arrays.asList(new Object[]{PR_PLAIN,
+                    Pattern.compile("^[a-z_$][a-z_$@0-9]*", Pattern.CASE_INSENSITIVE),
+                    null}));
+        fallthroughStylePatterns.add(Arrays.asList(new Object[]{PR_LITERAL,
+                    Pattern.compile("^(?:"
+                    // A hex number
+                    + "0x[a-f0-9]+"
+                    // or an octal or decimal number,
+                    + "|(?:\\d(?:_\\d+)*\\d*(?:\\.\\d*)?|\\.\\d\\+)"
+                    // possibly in scientific notation
+                    + "(?:e[+\\-]?\\d+)?"
+                    + ')'
+                    // with an optional modifier like UL for unsigned long
+                    + "[a-z]*", Pattern.CASE_INSENSITIVE),
+                    null,
+                    "0123456789"}));
+        // Don't treat escaped quotes in bash as starting strings.  See issue 144.
+        fallthroughStylePatterns.add(Arrays.asList(new Object[]{PR_PLAIN,
+                    Pattern.compile("^\\\\[\\s\\S]?"),
+                    null}));
+        fallthroughStylePatterns.add(Arrays.asList(new Object[]{PR_PUNCTUATION,
+                    Pattern.compile("^.[^\\s\\w\\.$@\\'\\\"\\`\\/\\#\\\\]*"),
+                    null}));
+
+        return new CreateSimpleLexer(shortcutStylePatterns, fallthroughStylePatterns);
+    }
+    /** Maps language-specific file extensions to handlers. */
+    protected Map<String, CreateSimpleLexer> langHandlerRegistry = new HashMap<String, CreateSimpleLexer>();
+
+    /** Register a language handler for the given file extensions.
+     * @param handler a function from source code to a list
+     *      of decorations.  Takes a single argument job which describes the
+     *      state of the computation.   The single parameter has the form
+     *      {@code {
+     *        sourceCode: {string} as plain text.
+     *        decorations: {Array.<number|string>} an array of style classes
+     *                     preceded by the position at which they start in
+     *                     job.sourceCode in order.
+     *                     The language handler should assigned this field.
+     *        basePos: {int} the position of source in the larger source chunk.
+     *                 All positions in the output decorations array are relative
+     *                 to the larger source chunk.
+     *      } }
+     * @param fileExtensions
+     */
+    public void registerLangHandler(CreateSimpleLexer handler, List<String> fileExtensions) throws Exception {
+        for (int i = fileExtensions.size(); --i >= 0;) {
+            String ext = fileExtensions.get(i);
+            if (langHandlerRegistry.get(ext) == null) {
+                langHandlerRegistry.put(ext, handler);
+            } else {
+                throw new Exception("cannot override language handler " + ext);
+            }
+        }
+    }
+
+    public CreateSimpleLexer langHandlerForExtension(String extension, String source) {
+        if (!(extension != null && langHandlerRegistry.get(extension) != null)) {
+            // Treat it as markup if the first non whitespace character is a < and
+            // the last non-whitespace character is a >.
+            extension = source.matches("^\\s&<")
+                    ? "default-markup"
+                    : "default-code";
+        }
+        return langHandlerRegistry.get(extension);
+    }
+
+    public static void main(String[] args) throws IOException {
+        Job job = new Job();
+        job.setBasePos(0);
+        job.setSourceCode(new String(Util.readResourceFile("/prettify/example.html")));
+        Prettify prettify = new Prettify();
+        prettify.langHandlerRegistry.get("html").decorate(job);
+        List<Object> decorations = job.getDecorations();
+        System.out.println(decorations);
+    }
+}
diff --git a/src/prettify/Util.java b/src/prettify/Util.java
new file mode 100644
index 0000000..3f53f93
--- /dev/null
+++ b/src/prettify/Util.java
@@ -0,0 +1,86 @@
+package prettify;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * @author Chan Wai Shing <cws1989@gmail.com>
+ */
+public class Util {
+
+    /**
+     * Read the resource file from the jar.
+     * @param path the resource path
+     * @return the content of the resource file in byte array
+     * @throws IOException error occurred when reading the content from the file
+     */
+    public static byte[] readResourceFile(String path) throws IOException {
+        if (path == null) {
+            throw new NullPointerException("argument 'path' cannot be null");
+        }
+
+        ByteArrayOutputStream bout = new ByteArrayOutputStream();
+        InputStream in = null;
+        try {
+            in = Util.class.getResourceAsStream(path);
+            if (in == null) {
+                throw new IOException("Resources not found: " + path);
+            }
+
+            int byteRead = 0;
+            byte[] b = new byte[8096];
+
+            while ((byteRead = in.read(b)) != -1) {
+                bout.write(b, 0, byteRead);
+            }
+        } finally {
+            if (in != null) {
+                try {
+                    in.close();
+                } catch (IOException ex) {
+                }
+            }
+        }
+
+        return bout.toByteArray();
+    }
+
+    public static String[] match(Pattern pattern, String string) {
+        List<String> matchesList = new ArrayList<String>();
+
+        Matcher matcher = pattern.matcher(string);
+        while (matcher.find()) {
+            matchesList.add(matcher.group(0));
+        }
+
+        return matchesList.toArray(new String[matchesList.size()]);
+    }
+
+    public static String join(List<String> strings) {
+        return join(strings.toArray(new String[strings.size()]));
+    }
+
+    public static String join(List<String> strings, String delimiter) {
+        return join(strings.toArray(new String[strings.size()]), delimiter);
+    }
+
+    public static String join(String[] strings) {
+        return join(strings, null);
+    }
+
+    public static String join(String[] strings, String delimiter) {
+        StringBuilder sb = new StringBuilder();
+        for (String string : strings) {
+            if (delimiter != null && sb.length() != 0) {
+                sb.append(delimiter);
+            }
+            sb.append(string);
+        }
+        return sb.toString();
+    }
+}
diff --git a/src/prettify/example.html b/src/prettify/example.html
new file mode 100644
index 0000000..1ef22ae
--- /dev/null
+++ b/src/prettify/example.html
@@ -0,0 +1,47 @@
+<html>

+<head>

+    <title> HTML Script Example </title>

+    <style type="text/css">

+        body {

+            font-family: Helvetica, Geneva, Arial, sans-serif;

+            font-size: 1em;

+            margin: 4em 15em 4em 4em;

+        }

+        body.with_sponsor { margin-right: 410px; }

+        a.external {

+            background: url(../images/external.png) right 50% no-repeat;

+            padding-right: 12px;

+        }

+        code, pre, .file-list {

+            font-family: Consolas, Monaco, "Bitstream Vera Sans Mono", "Courier New", Courier, monospace;

+        }

+    </style>

+    <script type="text/javascript">

+        var _gaq = _gaq || [];

+        _gaq.push(['_setAccount', 'UA-XXXXX-XX']);

+        _gaq.push(['_trackPageview']);

+

+        (function() {

+            var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;

+            ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';

+            var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);

+        })();

+    </script>

+</head>

+<body>

+

+<div style="font-weight: bold"><?= str_replace("\n", "<br/>", $var) ?></div>

+<?php

+    /***********************************

+    ** Multiline block comments

+    **********************************/

+

+    $stringWithUrl = "http://alexgorbatchev.com";

+    $stringWithUrl = 'http://alexgorbatchev.com';

+

+    ob_start("parseOutputBuffer");      // Start Code Buffering

+    session_start();

+?>

+

+</body>

+</html>
\ No newline at end of file