diff --git a/JSearchClient_nbproject/build.xml b/JSearchClient_nbproject/build.xml
new file mode 100644
index 0000000000000000000000000000000000000000..68df2ba7d4d34df73802e7d1d9d2b5535f5566a0
--- /dev/null
+++ b/JSearchClient_nbproject/build.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Sun designates this
+particular file as subject to the "Classpath" exception as provided
+by Sun in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+CA 95054 USA or visit www.sun.com if you need additional information or
+have any questions.
+ -->
+<project name="JSearchClient" default="default" basedir=".">
+    <description>Builds, tests, and runs the project JSearchClient.</description>
+    <import file="nbproject/build-impl.xml"/>
+</project>
diff --git a/JSearchClient_nbproject/manifest.mf b/JSearchClient_nbproject/manifest.mf
new file mode 100644
index 0000000000000000000000000000000000000000..1574df4a2de5d2884f33a5d3e30ae3daa5affee1
--- /dev/null
+++ b/JSearchClient_nbproject/manifest.mf
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+X-COMMENT: Main-Class will be added automatically by build
+
diff --git a/JSearchClient_nbproject/nbproject/build-impl.xml b/JSearchClient_nbproject/nbproject/build-impl.xml
new file mode 100644
index 0000000000000000000000000000000000000000..d6ce517eab8819c7b5057c17b05f5c3e34bfa27d
--- /dev/null
+++ b/JSearchClient_nbproject/nbproject/build-impl.xml
@@ -0,0 +1,545 @@
+<?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 name="JSearchClient-impl" default="default" basedir=".." xmlns:j2seproject3="http://www.netbeans.org/ns/j2se-project/3" xmlns:j2seproject2="http://www.netbeans.org/ns/j2se-project/2" xmlns:j2seproject1="http://www.netbeans.org/ns/j2se-project/1" xmlns:jaxws="http://www.netbeans.org/ns/jax-ws/1">
+    <target name="default" depends="test,jar,javadoc" description="Build and test whole project."/>
+    <!-- 
+    ======================
+    INITIALIZATION SECTION 
+    ======================
+    -->
+    <target name="-pre-init">
+        <!-- Empty placeholder for easier customization. -->
+        <!-- You can override this target in the ../build.xml file. -->
+    </target>
+    <target name="-init-private" depends="-pre-init">
+        <property file="nbproject/private/config.properties"/>
+        <property file="nbproject/private/configs/${config}.properties"/>
+        <property file="nbproject/private/private.properties"/>
+    </target>
+    <target name="-init-user" depends="-pre-init,-init-private">
+        <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 name="-init-project" depends="-pre-init,-init-private,-init-user">
+        <property file="nbproject/configs/${config}.properties"/>
+        <property file="nbproject/project.properties"/>
+    </target>
+    <target name="-do-init" depends="-pre-init,-init-private,-init-user,-init-project,-init-macrodef-property">
+        <available file="${manifest.file}" property="manifest.available"/>
+        <condition property="manifest.available+main.class">
+            <and>
+                <isset property="manifest.available"/>
+                <isset property="main.class"/>
+                <not>
+                    <equals arg1="${main.class}" arg2="" trim="true"/>
+                </not>
+            </and>
+        </condition>
+        <condition property="manifest.available+main.class+mkdist.available">
+            <and>
+                <istrue value="${manifest.available+main.class}"/>
+                <isset property="libs.CopyLibs.classpath"/>
+            </and>
+        </condition>
+        <condition property="have.tests">
+            <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">
+            <isfalse value="${javadoc.preview}"/>
+        </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=""/>
+    </target>
+    <target name="-post-init">
+        <!-- Empty placeholder for easier customization. -->
+        <!-- You can override this target in the ../build.xml file. -->
+    </target>
+    <target name="-init-check" depends="-pre-init,-init-private,-init-user,-init-project,-do-init">
+        <fail unless="src.dir">Must set 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 name="-init-macrodef-javac">
+        <macrodef name="javac" uri="http://www.netbeans.org/ns/j2se-project/3">
+            <attribute name="srcdir" default="${src.dir}"/>
+            <attribute name="destdir" default="${build.classes.dir}"/>
+            <attribute name="classpath" default="${javac.classpath}"/>
+            <attribute name="debug" default="${javac.debug}"/>
+            <element name="customize" optional="true"/>
+            <sequential>
+                <depend srcdir="@{srcdir}" destdir="@{destdir}" cache="${build.dir}/depcache">
+                    <classpath>
+                        <path path="@{classpath}"/>
+                    </classpath>
+                </depend>
+                <javac srcdir="@{srcdir}" destdir="@{destdir}" debug="@{debug}" deprecation="${javac.deprecation}" source="${javac.source}" target="${javac.target}" includeantruntime="false">
+                    <classpath>
+                        <path path="@{classpath}"/>
+                    </classpath>
+                    <compilerarg line="${javac.compilerargs}"/>
+                    <customize/>
+                </javac>
+            </sequential>
+        </macrodef>
+    </target>
+    <target name="-init-macrodef-junit">
+        <macrodef name="junit" uri="http://www.netbeans.org/ns/j2se-project/3">
+            <attribute name="includes" default="**/*Test.java"/>
+            <sequential>
+                <junit showoutput="true" fork="true" dir="${basedir}" failureproperty="tests.failed" errorproperty="tests.failed">
+                    <batchtest todir="${build.test.results.dir}"/>
+                    <classpath>
+                        <path path="${run.test.classpath}"/>
+                    </classpath>
+                    <syspropertyset>
+                        <propertyref prefix="test-sys-prop."/>
+                        <mapper type="glob" from="test-sys-prop.*" to="*"/>
+                    </syspropertyset>
+                    <formatter type="brief" usefile="false"/>
+                    <formatter type="xml"/>
+                    <jvmarg line="${run.jvmargs}"/>
+                </junit>
+            </sequential>
+        </macrodef>
+    </target>
+    <target name="-init-macrodef-nbjpda">
+        <macrodef name="nbjpdastart" uri="http://www.netbeans.org/ns/j2se-project/1">
+            <attribute name="name" default="${main.class}"/>
+            <attribute name="classpath" default="${debug.classpath}"/>
+            <attribute name="stopclassname" default=""/>
+            <sequential>
+                <nbjpdastart transport="dt_socket" addressproperty="jpda.address" name="@{name}" stopclassname="@{stopclassname}">
+                    <classpath>
+                        <path path="@{classpath}"/>
+                    </classpath>
+                </nbjpdastart>
+            </sequential>
+        </macrodef>
+        <macrodef name="nbjpdareload" uri="http://www.netbeans.org/ns/j2se-project/1">
+            <attribute name="dir" default="${build.classes.dir}"/>
+            <sequential>
+                <nbjpdareload>
+                    <fileset includes="${fix.includes}*.class" dir="@{dir}"/>
+                </nbjpdareload>
+            </sequential>
+        </macrodef>
+    </target>
+    <target name="-init-macrodef-debug">
+        <macrodef name="debug" uri="http://www.netbeans.org/ns/j2se-project/3">
+            <attribute name="classname" default="${main.class}"/>
+            <attribute name="classpath" default="${debug.classpath}"/>
+            <element name="customize" optional="true"/>
+            <sequential>
+                <java fork="true" classname="@{classname}" dir="${work.dir}">
+                    <jvmarg value="-Xdebug"/>
+                    <jvmarg value="-Xnoagent"/>
+                    <jvmarg value="-Djava.compiler=none"/>
+                    <jvmarg value="-Xrunjdwp:transport=dt_socket,address=${jpda.address}"/>
+                    <jvmarg line="${run.jvmargs}"/>
+                    <classpath>
+                        <path path="@{classpath}"/>
+                    </classpath>
+                    <syspropertyset>
+                        <propertyref prefix="run-sys-prop."/>
+                        <mapper type="glob" from="run-sys-prop.*" to="*"/>
+                    </syspropertyset>
+                    <customize/>
+                </java>
+            </sequential>
+        </macrodef>
+    </target>
+    <target name="-init-macrodef-java">
+        <macrodef name="java" uri="http://www.netbeans.org/ns/j2se-project/1">
+            <attribute name="classname" default="${main.class}"/>
+            <element name="customize" optional="true"/>
+            <sequential>
+                <java fork="true" classname="@{classname}" dir="${work.dir}">
+                    <jvmarg line="${run.jvmargs}"/>
+                    <classpath>
+                        <path path="${run.classpath}"/>
+                    </classpath>
+                    <syspropertyset>
+                        <propertyref prefix="run-sys-prop."/>
+                        <mapper type="glob" from="run-sys-prop.*" to="*"/>
+                    </syspropertyset>
+                    <customize/>
+                </java>
+            </sequential>
+        </macrodef>
+    </target>
+    <target name="-init-presetdef-jar">
+        <presetdef name="jar" uri="http://www.netbeans.org/ns/j2se-project/1">
+            <jar jarfile="${dist.jar}" compress="${jar.compress}">
+                <j2seproject1:fileset dir="${build.classes.dir}"/>
+            </jar>
+        </presetdef>
+    </target>
+    <target name="init" 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"/>
+    <!--
+    ===================
+    COMPILATION SECTION
+    ===================
+    -->
+    <target name="deps-jar" depends="init" unless="no.deps">
+        <ant target="jar" inheritall="false" antfile="${project.JavaHelp}/build.xml"/>
+    </target>
+    <target name="-pre-pre-compile" depends="init,deps-jar">
+        <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 name="-do-compile" depends="init,deps-jar,-pre-pre-compile,-pre-compile" if="have.sources">
+        <j2seproject3:javac/>
+        <copy todir="${build.classes.dir}">
+            <fileset dir="${src.dir}" excludes="${build.classes.excludes}"/>
+        </copy>
+    </target>
+    <target name="-post-compile">
+        <!-- Empty placeholder for easier customization. -->
+        <!-- You can override this target in the ../build.xml file. -->
+    </target>
+    <target name="compile" depends="init,deps-jar,-pre-pre-compile,-pre-compile,-do-compile,-post-compile" description="Compile project."/>
+    <target name="-pre-compile-single">
+        <!-- Empty placeholder for easier customization. -->
+        <!-- You can override this target in the ../build.xml file. -->
+    </target>
+    <target name="-do-compile-single" depends="init,deps-jar,-pre-pre-compile">
+        <fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail>
+        <j2seproject3:javac>
+            <customize>
+                <patternset includes="${javac.includes}"/>
+            </customize>
+        </j2seproject3:javac>
+    </target>
+    <target name="-post-compile-single">
+        <!-- Empty placeholder for easier customization. -->
+        <!-- You can override this target in the ../build.xml file. -->
+    </target>
+    <target name="compile-single" depends="init,deps-jar,-pre-pre-compile,-pre-compile-single,-do-compile-single,-post-compile-single"/>
+    <!--
+    ====================
+    JAR BUILDING SECTION
+    ====================
+    -->
+    <target name="-pre-pre-jar" depends="init">
+        <dirname property="dist.jar.dir" file="${dist.jar}"/>
+        <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 name="-do-jar-without-manifest" depends="init,compile,-pre-pre-jar,-pre-jar" unless="manifest.available">
+        <j2seproject1:jar/>
+    </target>
+    <target name="-do-jar-with-manifest" depends="init,compile,-pre-pre-jar,-pre-jar" if="manifest.available" unless="manifest.available+main.class">
+        <j2seproject1:jar manifest="${manifest.file}"/>
+    </target>
+    <target name="-do-jar-with-mainclass" depends="init,compile,-pre-pre-jar,-pre-jar" if="manifest.available+main.class" 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>To run this application from the command line without Ant, try:</echo>
+        <property name="build.classes.dir.resolved" location="${build.classes.dir}"/>
+        <property name="dist.jar.resolved" location="${dist.jar}"/>
+        <pathconvert property="run.classpath.with.dist.jar">
+            <path path="${run.classpath}"/>
+            <map from="${build.classes.dir.resolved}" to="${dist.jar.resolved}"/>
+        </pathconvert>
+        <echo>java -cp "${run.classpath.with.dist.jar}" ${main.class}</echo>
+    </target>
+    <target name="-do-jar-with-libraries" depends="init,compile,-pre-pre-jar,-pre-jar" if="manifest.available+main.class+mkdist.available">
+        <property name="build.classes.dir.resolved" location="${build.classes.dir}"/>
+        <pathconvert property="run.classpath.without.build.classes.dir">
+            <path path="${run.classpath}"/>
+            <map from="${build.classes.dir.resolved}" to=""/>
+        </pathconvert>
+        <pathconvert property="jar.classpath" pathsep=" ">
+            <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" name="copylibs" classpath="${libs.CopyLibs.classpath}"/>
+        <copylibs manifest="${manifest.file}" runtimeclasspath="${run.classpath.without.build.classes.dir}" jarfile="${dist.jar}" compress="${jar.compress}">
+            <fileset dir="${build.classes.dir}"/>
+            <manifest>
+                <attribute name="Main-Class" value="${main.class}"/>
+                <attribute name="Class-Path" value="${jar.classpath}"/>
+            </manifest>
+        </copylibs>
+        <echo>To run this application from the command line without Ant, try:</echo>
+        <property name="dist.jar.resolved" location="${dist.jar}"/>
+        <echo>java -jar "${dist.jar.resolved}"</echo>
+    </target>
+    <target name="-post-jar">
+        <!-- Empty placeholder for easier customization. -->
+        <!-- You can override this target in the ../build.xml file. -->
+    </target>
+    <target name="jar" 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."/>
+    <!--
+    =================
+    EXECUTION SECTION
+    =================
+    -->
+    <target name="run" depends="init,compile" description="Run a main class.">
+        <j2seproject1:java>
+            <customize>
+                <arg line="${application.args}"/>
+            </customize>
+        </j2seproject1:java>
+    </target>
+    <target name="run-single" depends="init,compile-single">
+        <fail unless="run.class">Must select one file in the IDE or set run.class</fail>
+        <j2seproject1:java classname="${run.class}"/>
+    </target>
+    <!--
+    =================
+    DEBUGGING SECTION
+    =================
+    -->
+    <target name="-debug-start-debugger" if="netbeans.home" depends="init">
+        <j2seproject1:nbjpdastart name="${debug.class}"/>
+    </target>
+    <target name="-debug-start-debuggee" depends="init,compile">
+        <j2seproject3:debug>
+            <customize>
+                <arg line="${application.args}"/>
+            </customize>
+        </j2seproject3:debug>
+    </target>
+    <target name="debug" if="netbeans.home" depends="init,compile,-debug-start-debugger,-debug-start-debuggee" description="Debug project in IDE."/>
+    <target name="-debug-start-debugger-stepinto" if="netbeans.home" depends="init">
+        <j2seproject1:nbjpdastart stopclassname="${main.class}"/>
+    </target>
+    <target name="debug-stepinto" if="netbeans.home" depends="init,compile,-debug-start-debugger-stepinto,-debug-start-debuggee"/>
+    <target name="-debug-start-debuggee-single" if="netbeans.home" depends="init,compile-single">
+        <fail unless="debug.class">Must select one file in the IDE or set debug.class</fail>
+        <j2seproject3:debug classname="${debug.class}"/>
+    </target>
+    <target name="debug-single" if="netbeans.home" depends="init,compile-single,-debug-start-debugger,-debug-start-debuggee-single"/>
+    <target name="-pre-debug-fix" depends="init">
+        <fail unless="fix.includes">Must set fix.includes</fail>
+        <property name="javac.includes" value="${fix.includes}.java"/>
+    </target>
+    <target name="-do-debug-fix" if="netbeans.home" depends="init,-pre-debug-fix,compile-single">
+        <j2seproject1:nbjpdareload/>
+    </target>
+    <target name="debug-fix" if="netbeans.home" depends="init,-pre-debug-fix,-do-debug-fix"/>
+    <!--
+    ===============
+    JAVADOC SECTION
+    ===============
+    -->
+    <target name="-javadoc-build" depends="init">
+        <mkdir dir="${dist.javadoc.dir}"/>
+        <javadoc destdir="${dist.javadoc.dir}" source="${javac.source}" notree="${javadoc.notree}" use="${javadoc.use}" nonavbar="${javadoc.nonavbar}" noindex="${javadoc.noindex}" splitindex="${javadoc.splitindex}" author="${javadoc.author}" version="${javadoc.version}" windowtitle="${javadoc.windowtitle}" private="${javadoc.private}" additionalparam="${javadoc.additionalparam}" failonerror="true" useexternalfile="true">
+            <classpath>
+                <path path="${javac.classpath}"/>
+            </classpath>
+            <sourcepath>
+                <pathelement location="${src.dir}"/>
+            </sourcepath>
+            <packageset dir="${src.dir}" includes="*/**"/>
+            <fileset dir="${src.dir}" includes="*.java"/>
+        </javadoc>
+    </target>
+    <target name="-javadoc-browse" if="netbeans.home" unless="no.javadoc.preview" depends="init,-javadoc-build">
+        <nbbrowse file="${dist.javadoc.dir}/index.html"/>
+    </target>
+    <target name="javadoc" depends="init,-javadoc-build,-javadoc-browse" description="Build Javadoc."/>
+    <!--
+    =========================
+    JUNIT COMPILATION SECTION
+    =========================
+    -->
+    <target name="-pre-pre-compile-test" if="have.tests" depends="init,compile">
+        <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 name="-do-compile-test" if="have.tests" depends="init,compile,-pre-pre-compile-test,-pre-compile-test">
+        <j2seproject3:javac srcdir="" destdir="${build.test.classes.dir}" debug="true" classpath="${javac.test.classpath}"/>
+        <copy todir="${build.test.classes.dir}"/>
+    </target>
+    <target name="-post-compile-test">
+        <!-- Empty placeholder for easier customization. -->
+        <!-- You can override this target in the ../build.xml file. -->
+    </target>
+    <target name="compile-test" depends="init,compile,-pre-pre-compile-test,-pre-compile-test,-do-compile-test,-post-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 name="-do-compile-test-single" if="have.tests" depends="init,compile,-pre-pre-compile-test,-pre-compile-test-single">
+        <fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail>
+        <j2seproject3:javac srcdir="" destdir="${build.test.classes.dir}" debug="true" classpath="${javac.test.classpath}">
+            <customize>
+                <patternset includes="${javac.includes}"/>
+            </customize>
+        </j2seproject3:javac>
+        <copy todir="${build.test.classes.dir}"/>
+    </target>
+    <target name="-post-compile-test-single">
+        <!-- Empty placeholder for easier customization. -->
+        <!-- You can override this target in the ../build.xml file. -->
+    </target>
+    <target name="compile-test-single" depends="init,compile,-pre-pre-compile-test,-pre-compile-test-single,-do-compile-test-single,-post-compile-test-single"/>
+    <!--
+    =======================
+    JUNIT EXECUTION SECTION
+    =======================
+    -->
+    <target name="-pre-test-run" if="have.tests" depends="init">
+        <mkdir dir="${build.test.results.dir}"/>
+    </target>
+    <target name="-do-test-run" if="have.tests" depends="init,compile-test,-pre-test-run">
+        <j2seproject3:junit/>
+    </target>
+    <target name="-post-test-run" if="have.tests" depends="init,compile-test,-pre-test-run,-do-test-run">
+        <fail if="tests.failed">Some tests failed; see details above.</fail>
+    </target>
+    <target name="test-report" if="have.tests" depends="init"/>
+    <target name="-test-browse" if="netbeans.home+have.tests" depends="init"/>
+    <target name="test" depends="init,compile-test,-pre-test-run,-do-test-run,test-report,-post-test-run,-test-browse" description="Run unit tests."/>
+    <target name="-pre-test-run-single" if="have.tests" depends="init">
+        <mkdir dir="${build.test.results.dir}"/>
+    </target>
+    <target name="-do-test-run-single" if="have.tests" depends="init,compile-test-single,-pre-test-run-single">
+        <fail unless="test.includes">Must select some files in the IDE or set test.includes</fail>
+        <j2seproject3:junit includes="${test.includes}"/>
+    </target>
+    <target name="-post-test-run-single" if="have.tests" depends="init,compile-test-single,-pre-test-run-single,-do-test-run-single">
+        <fail if="tests.failed">Some tests failed; see details above.</fail>
+    </target>
+    <target name="test-single" depends="init,compile-test-single,-pre-test-run-single,-do-test-run-single,-post-test-run-single" description="Run single unit test."/>
+    <!--
+    =======================
+    JUNIT DEBUGGING SECTION
+    =======================
+    -->
+    <target name="-debug-start-debuggee-test" if="have.tests" depends="init,compile-test">
+        <fail unless="test.class">Must select one file in the IDE or set test.class</fail>
+        <j2seproject3:debug classname="junit.textui.TestRunner" classpath="${debug.test.classpath}">
+            <customize>
+                <arg line="${test.class}"/>
+            </customize>
+        </j2seproject3:debug>
+    </target>
+    <target name="-debug-start-debugger-test" if="netbeans.home+have.tests" depends="init,compile-test">
+        <j2seproject1:nbjpdastart name="${test.class}" classpath="${debug.test.classpath}"/>
+    </target>
+    <target name="debug-test" depends="init,compile-test,-debug-start-debugger-test,-debug-start-debuggee-test"/>
+    <target name="-do-debug-fix-test" if="netbeans.home" depends="init,-pre-debug-fix,compile-test-single">
+        <j2seproject1:nbjpdareload dir="${build.test.classes.dir}"/>
+    </target>
+    <target name="debug-fix-test" if="netbeans.home" depends="init,-pre-debug-fix,-do-debug-fix-test"/>
+    <!--
+    =========================
+    APPLET EXECUTION SECTION
+    =========================
+    -->
+    <target name="run-applet" depends="init,compile-single">
+        <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 name="-debug-start-debuggee-applet" if="netbeans.home" depends="init,compile-single">
+        <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 name="debug-applet" if="netbeans.home" depends="init,compile-single,-debug-start-debugger,-debug-start-debuggee-applet"/>
+    <!--
+    ===============
+    CLEANUP SECTION
+    ===============
+    -->
+    <target name="deps-clean" depends="init" unless="no.deps">
+        <ant target="clean" inheritall="false" antfile="${project.JavaHelp}/build.xml"/>
+    </target>
+    <target name="-do-clean" depends="init">
+        <delete dir="${build.dir}"/>
+        <delete dir="${dist.dir}"/>
+    </target>
+    <target name="-post-clean">
+        <!-- Empty placeholder for easier customization. -->
+        <!-- You can override this target in the ../build.xml file. -->
+    </target>
+    <target name="clean" depends="init,deps-clean,-do-clean,-post-clean" description="Clean build products."/>
+</project>
diff --git a/JSearchClient_nbproject/nbproject/genfiles.properties b/JSearchClient_nbproject/nbproject/genfiles.properties
new file mode 100644
index 0000000000000000000000000000000000000000..da3fc0161ff92acd7ba33a233abc72010e4a19d0
--- /dev/null
+++ b/JSearchClient_nbproject/nbproject/genfiles.properties
@@ -0,0 +1,8 @@
+build.xml.data.CRC32=c5c19be1
+build.xml.script.CRC32=3f707102
+build.xml.stylesheet.CRC32=a12b3d02
+# 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=c5c19be1
+nbproject/build-impl.xml.script.CRC32=36526266
+nbproject/build-impl.xml.stylesheet.CRC32=2093e0f1
diff --git a/JSearchClient_nbproject/nbproject/project.properties b/JSearchClient_nbproject/nbproject/project.properties
new file mode 100644
index 0000000000000000000000000000000000000000..9e510f59bdf3b126aadd3d1b39a2f8ee9ead2772
--- /dev/null
+++ b/JSearchClient_nbproject/nbproject/project.properties
@@ -0,0 +1,80 @@
+# Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+# 
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.  Sun designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Sun in the LICENSE file that accompanied this code.
+# 
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+# 
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+# 
+# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+# CA 95054 USA or visit www.sun.com if you need additional information or
+# have any questions.
+build.classes.dir=${build.dir}/classes
+build.classes.excludes=**/*.java,**/*.form,**/*.html,GNUmakefile
+# This directory is removed when the project is cleaned:
+build.dir=build
+build.generated.dir=${build.dir}/generated
+# 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
+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}/jsearch-client.jar
+dist.javadoc.dir=${dist.dir}/javadoc
+file.reference.JSearch-client=../jhMaster/JSearch/client
+jar.compress=false
+javac.classpath=\
+    ${reference.JavaHelp.jar}
+# Space-separated list of extra javac options
+javac.compilerargs=
+javac.deprecation=false
+javac.source=1.4
+javac.target=1.4
+javac.test.classpath=\
+    ${javac.classpath}:\
+    ${build.classes.dir}:\
+    ${libs.junit.classpath}
+javadoc.additionalparam=
+javadoc.author=false
+javadoc.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
+platform.active=default_platform
+project.JavaHelp=../javahelp_nbproject
+reference.JavaHelp.jar=${project.JavaHelp}/dist/lib/jh-client.jar
+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}
+src.dir=${file.reference.JSearch-client}
diff --git a/JSearchClient_nbproject/nbproject/project.xml b/JSearchClient_nbproject/nbproject/project.xml
new file mode 100644
index 0000000000000000000000000000000000000000..81af24d06b651085a9f92ae6cfd24f9299f3e717
--- /dev/null
+++ b/JSearchClient_nbproject/nbproject/project.xml
@@ -0,0 +1,24 @@
+<?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>JSearchClient</name>
+            <minimum-ant-version>1.6.5</minimum-ant-version>
+            <source-roots>
+                <root id="src.dir"/>
+            </source-roots>
+            <test-roots/>
+        </data>
+        <references xmlns="http://www.netbeans.org/ns/ant-project-references/1">
+            <reference>
+                <foreign-project>JavaHelp</foreign-project>
+                <artifact-type>jar</artifact-type>
+                <script>build.xml</script>
+                <target>jar</target>
+                <clean-target>clean</clean-target>
+                <id>jar</id>
+            </reference>
+        </references>
+    </configuration>
+</project>
diff --git a/JSearchIndexer_nbproject/build.xml b/JSearchIndexer_nbproject/build.xml
new file mode 100644
index 0000000000000000000000000000000000000000..b7da7d3972b65ef966ef61437aa41354626f1791
--- /dev/null
+++ b/JSearchIndexer_nbproject/build.xml
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Sun designates this
+particular file as subject to the "Classpath" exception as provided
+by Sun in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+CA 95054 USA or visit www.sun.com if you need additional information or
+have any questions.
+ -->
+<project name="JSearchIndexer" default="default" basedir=".">
+    <description>Builds, tests, and runs the project JSearchIndexer.</description>
+    <import file="nbproject/build-impl.xml"/>
+
+    <target name="-post-jar">
+        <echo>Creating merged jsearch.jar</echo>
+        <jar jarfile="${basedir}/dist/jsearch.jar" excludes="${build.classes.excludes}">
+            <fileset dir="${basedir}/build/classes">
+                <include name="**/*"/>
+            </fileset>
+            <fileset dir="../JSearchClient_nbproject/build/classes/">
+                <include name="**/*"/>
+            </fileset>
+            <fileset dir="../javahelp_nbproject/build/classes/">
+                <include name="com/sun/java/help/impl/HeaderParser.class"/>
+                <include name="javax/help/HelpUtilities*.class"/>
+                <include name="javax/help/event/EventListenerList.class"/>
+                <include name="javax/help/search/ConfigFile.class"/>
+                <include name="javax/help/search/ConfigFile.class"/>
+                <include name="javax/help/search/IndexBuilder.class"/>
+                <include name="javax/help/search/IndexerKit.class"/>
+                <include name="javax/help/search/SearchEngine.class"/>
+                <include name="javax/help/search/SearchEvent.class"/>
+                <include name="javax/help/search/SearchItem.class"/>
+                <include name="javax/help/search/SearchQuery.class"/>
+                <include name="javax/help/search/SearchListener.class"/>
+            </fileset>
+        </jar>
+        <echo>Creating jsearch-misc.jar</echo>
+        
+        <jar jarfile="${basedir}/dist/jsearch-misc.jar">
+            <fileset dir="../javahelp_nbproject/build/classes/">
+                <include name="com/sun/java/help/impl/HeaderParser.class"/>
+                <include name="javax/help/HelpUtilities*.class"/>
+                <include name="javax/help/event/EventListenerList.class"/>
+                <include name="javax/help/search/ConfigFile.class"/>
+                <include name="javax/help/search/ConfigFile.class"/>
+                <include name="javax/help/search/IndexBuilder.class"/>
+                <include name="javax/help/search/IndexerKit.class"/>
+                <include name="javax/help/search/SearchEngine.class"/>
+                <include name="javax/help/search/SearchEvent.class"/>
+                <include name="javax/help/search/SearchItem.class"/>
+                <include name="javax/help/search/SearchQuery.class"/>
+                <include name="javax/help/search/SearchListener.class"/>
+            </fileset>
+        </jar>
+    </target>
+</project>
diff --git a/JSearchIndexer_nbproject/manifest.mf b/JSearchIndexer_nbproject/manifest.mf
new file mode 100644
index 0000000000000000000000000000000000000000..1574df4a2de5d2884f33a5d3e30ae3daa5affee1
--- /dev/null
+++ b/JSearchIndexer_nbproject/manifest.mf
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+X-COMMENT: Main-Class will be added automatically by build
+
diff --git a/JSearchIndexer_nbproject/nbproject/build-impl.xml b/JSearchIndexer_nbproject/nbproject/build-impl.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e1072fd67d48463e2b434be167f567fe2a23af1f
--- /dev/null
+++ b/JSearchIndexer_nbproject/nbproject/build-impl.xml
@@ -0,0 +1,547 @@
+<?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 name="JSearchIndexer-impl" default="default" basedir=".." xmlns:j2seproject3="http://www.netbeans.org/ns/j2se-project/3" xmlns:j2seproject2="http://www.netbeans.org/ns/j2se-project/2" xmlns:j2seproject1="http://www.netbeans.org/ns/j2se-project/1" xmlns:jaxws="http://www.netbeans.org/ns/jax-ws/1">
+    <target name="default" depends="test,jar,javadoc" description="Build and test whole project."/>
+    <!-- 
+    ======================
+    INITIALIZATION SECTION 
+    ======================
+    -->
+    <target name="-pre-init">
+        <!-- Empty placeholder for easier customization. -->
+        <!-- You can override this target in the ../build.xml file. -->
+    </target>
+    <target name="-init-private" depends="-pre-init">
+        <property file="nbproject/private/config.properties"/>
+        <property file="nbproject/private/configs/${config}.properties"/>
+        <property file="nbproject/private/private.properties"/>
+    </target>
+    <target name="-init-user" depends="-pre-init,-init-private">
+        <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 name="-init-project" depends="-pre-init,-init-private,-init-user">
+        <property file="nbproject/configs/${config}.properties"/>
+        <property file="nbproject/project.properties"/>
+    </target>
+    <target name="-do-init" depends="-pre-init,-init-private,-init-user,-init-project,-init-macrodef-property">
+        <available file="${manifest.file}" property="manifest.available"/>
+        <condition property="manifest.available+main.class">
+            <and>
+                <isset property="manifest.available"/>
+                <isset property="main.class"/>
+                <not>
+                    <equals arg1="${main.class}" arg2="" trim="true"/>
+                </not>
+            </and>
+        </condition>
+        <condition property="manifest.available+main.class+mkdist.available">
+            <and>
+                <istrue value="${manifest.available+main.class}"/>
+                <isset property="libs.CopyLibs.classpath"/>
+            </and>
+        </condition>
+        <condition property="have.tests">
+            <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">
+            <isfalse value="${javadoc.preview}"/>
+        </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=""/>
+    </target>
+    <target name="-post-init">
+        <!-- Empty placeholder for easier customization. -->
+        <!-- You can override this target in the ../build.xml file. -->
+    </target>
+    <target name="-init-check" depends="-pre-init,-init-private,-init-user,-init-project,-do-init">
+        <fail unless="src.dir">Must set 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 name="-init-macrodef-javac">
+        <macrodef name="javac" uri="http://www.netbeans.org/ns/j2se-project/3">
+            <attribute name="srcdir" default="${src.dir}"/>
+            <attribute name="destdir" default="${build.classes.dir}"/>
+            <attribute name="classpath" default="${javac.classpath}"/>
+            <attribute name="debug" default="${javac.debug}"/>
+            <element name="customize" optional="true"/>
+            <sequential>
+                <depend srcdir="@{srcdir}" destdir="@{destdir}" cache="${build.dir}/depcache">
+                    <classpath>
+                        <path path="@{classpath}"/>
+                    </classpath>
+                </depend>
+                <javac srcdir="@{srcdir}" destdir="@{destdir}" debug="@{debug}" deprecation="${javac.deprecation}" source="${javac.source}" target="${javac.target}" includeantruntime="false">
+                    <classpath>
+                        <path path="@{classpath}"/>
+                    </classpath>
+                    <compilerarg line="${javac.compilerargs}"/>
+                    <customize/>
+                </javac>
+            </sequential>
+        </macrodef>
+    </target>
+    <target name="-init-macrodef-junit">
+        <macrodef name="junit" uri="http://www.netbeans.org/ns/j2se-project/3">
+            <attribute name="includes" default="**/*Test.java"/>
+            <sequential>
+                <junit showoutput="true" fork="true" dir="${basedir}" failureproperty="tests.failed" errorproperty="tests.failed">
+                    <batchtest todir="${build.test.results.dir}"/>
+                    <classpath>
+                        <path path="${run.test.classpath}"/>
+                    </classpath>
+                    <syspropertyset>
+                        <propertyref prefix="test-sys-prop."/>
+                        <mapper type="glob" from="test-sys-prop.*" to="*"/>
+                    </syspropertyset>
+                    <formatter type="brief" usefile="false"/>
+                    <formatter type="xml"/>
+                    <jvmarg line="${run.jvmargs}"/>
+                </junit>
+            </sequential>
+        </macrodef>
+    </target>
+    <target name="-init-macrodef-nbjpda">
+        <macrodef name="nbjpdastart" uri="http://www.netbeans.org/ns/j2se-project/1">
+            <attribute name="name" default="${main.class}"/>
+            <attribute name="classpath" default="${debug.classpath}"/>
+            <attribute name="stopclassname" default=""/>
+            <sequential>
+                <nbjpdastart transport="dt_socket" addressproperty="jpda.address" name="@{name}" stopclassname="@{stopclassname}">
+                    <classpath>
+                        <path path="@{classpath}"/>
+                    </classpath>
+                </nbjpdastart>
+            </sequential>
+        </macrodef>
+        <macrodef name="nbjpdareload" uri="http://www.netbeans.org/ns/j2se-project/1">
+            <attribute name="dir" default="${build.classes.dir}"/>
+            <sequential>
+                <nbjpdareload>
+                    <fileset includes="${fix.includes}*.class" dir="@{dir}"/>
+                </nbjpdareload>
+            </sequential>
+        </macrodef>
+    </target>
+    <target name="-init-macrodef-debug">
+        <macrodef name="debug" uri="http://www.netbeans.org/ns/j2se-project/3">
+            <attribute name="classname" default="${main.class}"/>
+            <attribute name="classpath" default="${debug.classpath}"/>
+            <element name="customize" optional="true"/>
+            <sequential>
+                <java fork="true" classname="@{classname}" dir="${work.dir}">
+                    <jvmarg value="-Xdebug"/>
+                    <jvmarg value="-Xnoagent"/>
+                    <jvmarg value="-Djava.compiler=none"/>
+                    <jvmarg value="-Xrunjdwp:transport=dt_socket,address=${jpda.address}"/>
+                    <jvmarg line="${run.jvmargs}"/>
+                    <classpath>
+                        <path path="@{classpath}"/>
+                    </classpath>
+                    <syspropertyset>
+                        <propertyref prefix="run-sys-prop."/>
+                        <mapper type="glob" from="run-sys-prop.*" to="*"/>
+                    </syspropertyset>
+                    <customize/>
+                </java>
+            </sequential>
+        </macrodef>
+    </target>
+    <target name="-init-macrodef-java">
+        <macrodef name="java" uri="http://www.netbeans.org/ns/j2se-project/1">
+            <attribute name="classname" default="${main.class}"/>
+            <element name="customize" optional="true"/>
+            <sequential>
+                <java fork="true" classname="@{classname}" dir="${work.dir}">
+                    <jvmarg line="${run.jvmargs}"/>
+                    <classpath>
+                        <path path="${run.classpath}"/>
+                    </classpath>
+                    <syspropertyset>
+                        <propertyref prefix="run-sys-prop."/>
+                        <mapper type="glob" from="run-sys-prop.*" to="*"/>
+                    </syspropertyset>
+                    <customize/>
+                </java>
+            </sequential>
+        </macrodef>
+    </target>
+    <target name="-init-presetdef-jar">
+        <presetdef name="jar" uri="http://www.netbeans.org/ns/j2se-project/1">
+            <jar jarfile="${dist.jar}" compress="${jar.compress}">
+                <j2seproject1:fileset dir="${build.classes.dir}"/>
+            </jar>
+        </presetdef>
+    </target>
+    <target name="init" 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"/>
+    <!--
+    ===================
+    COMPILATION SECTION
+    ===================
+    -->
+    <target name="deps-jar" depends="init" unless="no.deps">
+        <ant target="jar" inheritall="false" antfile="${project.JSearchClient}/build.xml"/>
+        <ant target="jar" inheritall="false" antfile="${project.JavaHelp}/build.xml"/>
+    </target>
+    <target name="-pre-pre-compile" depends="init,deps-jar">
+        <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 name="-do-compile" depends="init,deps-jar,-pre-pre-compile,-pre-compile" if="have.sources">
+        <j2seproject3:javac/>
+        <copy todir="${build.classes.dir}">
+            <fileset dir="${src.dir}" excludes="${build.classes.excludes}"/>
+        </copy>
+    </target>
+    <target name="-post-compile">
+        <!-- Empty placeholder for easier customization. -->
+        <!-- You can override this target in the ../build.xml file. -->
+    </target>
+    <target name="compile" depends="init,deps-jar,-pre-pre-compile,-pre-compile,-do-compile,-post-compile" description="Compile project."/>
+    <target name="-pre-compile-single">
+        <!-- Empty placeholder for easier customization. -->
+        <!-- You can override this target in the ../build.xml file. -->
+    </target>
+    <target name="-do-compile-single" depends="init,deps-jar,-pre-pre-compile">
+        <fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail>
+        <j2seproject3:javac>
+            <customize>
+                <patternset includes="${javac.includes}"/>
+            </customize>
+        </j2seproject3:javac>
+    </target>
+    <target name="-post-compile-single">
+        <!-- Empty placeholder for easier customization. -->
+        <!-- You can override this target in the ../build.xml file. -->
+    </target>
+    <target name="compile-single" depends="init,deps-jar,-pre-pre-compile,-pre-compile-single,-do-compile-single,-post-compile-single"/>
+    <!--
+    ====================
+    JAR BUILDING SECTION
+    ====================
+    -->
+    <target name="-pre-pre-jar" depends="init">
+        <dirname property="dist.jar.dir" file="${dist.jar}"/>
+        <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 name="-do-jar-without-manifest" depends="init,compile,-pre-pre-jar,-pre-jar" unless="manifest.available">
+        <j2seproject1:jar/>
+    </target>
+    <target name="-do-jar-with-manifest" depends="init,compile,-pre-pre-jar,-pre-jar" if="manifest.available" unless="manifest.available+main.class">
+        <j2seproject1:jar manifest="${manifest.file}"/>
+    </target>
+    <target name="-do-jar-with-mainclass" depends="init,compile,-pre-pre-jar,-pre-jar" if="manifest.available+main.class" 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>To run this application from the command line without Ant, try:</echo>
+        <property name="build.classes.dir.resolved" location="${build.classes.dir}"/>
+        <property name="dist.jar.resolved" location="${dist.jar}"/>
+        <pathconvert property="run.classpath.with.dist.jar">
+            <path path="${run.classpath}"/>
+            <map from="${build.classes.dir.resolved}" to="${dist.jar.resolved}"/>
+        </pathconvert>
+        <echo>java -cp "${run.classpath.with.dist.jar}" ${main.class}</echo>
+    </target>
+    <target name="-do-jar-with-libraries" depends="init,compile,-pre-pre-jar,-pre-jar" if="manifest.available+main.class+mkdist.available">
+        <property name="build.classes.dir.resolved" location="${build.classes.dir}"/>
+        <pathconvert property="run.classpath.without.build.classes.dir">
+            <path path="${run.classpath}"/>
+            <map from="${build.classes.dir.resolved}" to=""/>
+        </pathconvert>
+        <pathconvert property="jar.classpath" pathsep=" ">
+            <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" name="copylibs" classpath="${libs.CopyLibs.classpath}"/>
+        <copylibs manifest="${manifest.file}" runtimeclasspath="${run.classpath.without.build.classes.dir}" jarfile="${dist.jar}" compress="${jar.compress}">
+            <fileset dir="${build.classes.dir}"/>
+            <manifest>
+                <attribute name="Main-Class" value="${main.class}"/>
+                <attribute name="Class-Path" value="${jar.classpath}"/>
+            </manifest>
+        </copylibs>
+        <echo>To run this application from the command line without Ant, try:</echo>
+        <property name="dist.jar.resolved" location="${dist.jar}"/>
+        <echo>java -jar "${dist.jar.resolved}"</echo>
+    </target>
+    <target name="-post-jar">
+        <!-- Empty placeholder for easier customization. -->
+        <!-- You can override this target in the ../build.xml file. -->
+    </target>
+    <target name="jar" 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."/>
+    <!--
+    =================
+    EXECUTION SECTION
+    =================
+    -->
+    <target name="run" depends="init,compile" description="Run a main class.">
+        <j2seproject1:java>
+            <customize>
+                <arg line="${application.args}"/>
+            </customize>
+        </j2seproject1:java>
+    </target>
+    <target name="run-single" depends="init,compile-single">
+        <fail unless="run.class">Must select one file in the IDE or set run.class</fail>
+        <j2seproject1:java classname="${run.class}"/>
+    </target>
+    <!--
+    =================
+    DEBUGGING SECTION
+    =================
+    -->
+    <target name="-debug-start-debugger" if="netbeans.home" depends="init">
+        <j2seproject1:nbjpdastart name="${debug.class}"/>
+    </target>
+    <target name="-debug-start-debuggee" depends="init,compile">
+        <j2seproject3:debug>
+            <customize>
+                <arg line="${application.args}"/>
+            </customize>
+        </j2seproject3:debug>
+    </target>
+    <target name="debug" if="netbeans.home" depends="init,compile,-debug-start-debugger,-debug-start-debuggee" description="Debug project in IDE."/>
+    <target name="-debug-start-debugger-stepinto" if="netbeans.home" depends="init">
+        <j2seproject1:nbjpdastart stopclassname="${main.class}"/>
+    </target>
+    <target name="debug-stepinto" if="netbeans.home" depends="init,compile,-debug-start-debugger-stepinto,-debug-start-debuggee"/>
+    <target name="-debug-start-debuggee-single" if="netbeans.home" depends="init,compile-single">
+        <fail unless="debug.class">Must select one file in the IDE or set debug.class</fail>
+        <j2seproject3:debug classname="${debug.class}"/>
+    </target>
+    <target name="debug-single" if="netbeans.home" depends="init,compile-single,-debug-start-debugger,-debug-start-debuggee-single"/>
+    <target name="-pre-debug-fix" depends="init">
+        <fail unless="fix.includes">Must set fix.includes</fail>
+        <property name="javac.includes" value="${fix.includes}.java"/>
+    </target>
+    <target name="-do-debug-fix" if="netbeans.home" depends="init,-pre-debug-fix,compile-single">
+        <j2seproject1:nbjpdareload/>
+    </target>
+    <target name="debug-fix" if="netbeans.home" depends="init,-pre-debug-fix,-do-debug-fix"/>
+    <!--
+    ===============
+    JAVADOC SECTION
+    ===============
+    -->
+    <target name="-javadoc-build" depends="init">
+        <mkdir dir="${dist.javadoc.dir}"/>
+        <javadoc destdir="${dist.javadoc.dir}" source="${javac.source}" notree="${javadoc.notree}" use="${javadoc.use}" nonavbar="${javadoc.nonavbar}" noindex="${javadoc.noindex}" splitindex="${javadoc.splitindex}" author="${javadoc.author}" version="${javadoc.version}" windowtitle="${javadoc.windowtitle}" private="${javadoc.private}" additionalparam="${javadoc.additionalparam}" failonerror="true" useexternalfile="true">
+            <classpath>
+                <path path="${javac.classpath}"/>
+            </classpath>
+            <sourcepath>
+                <pathelement location="${src.dir}"/>
+            </sourcepath>
+            <packageset dir="${src.dir}" includes="*/**"/>
+            <fileset dir="${src.dir}" includes="*.java"/>
+        </javadoc>
+    </target>
+    <target name="-javadoc-browse" if="netbeans.home" unless="no.javadoc.preview" depends="init,-javadoc-build">
+        <nbbrowse file="${dist.javadoc.dir}/index.html"/>
+    </target>
+    <target name="javadoc" depends="init,-javadoc-build,-javadoc-browse" description="Build Javadoc."/>
+    <!--
+    =========================
+    JUNIT COMPILATION SECTION
+    =========================
+    -->
+    <target name="-pre-pre-compile-test" if="have.tests" depends="init,compile">
+        <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 name="-do-compile-test" if="have.tests" depends="init,compile,-pre-pre-compile-test,-pre-compile-test">
+        <j2seproject3:javac srcdir="" destdir="${build.test.classes.dir}" debug="true" classpath="${javac.test.classpath}"/>
+        <copy todir="${build.test.classes.dir}"/>
+    </target>
+    <target name="-post-compile-test">
+        <!-- Empty placeholder for easier customization. -->
+        <!-- You can override this target in the ../build.xml file. -->
+    </target>
+    <target name="compile-test" depends="init,compile,-pre-pre-compile-test,-pre-compile-test,-do-compile-test,-post-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 name="-do-compile-test-single" if="have.tests" depends="init,compile,-pre-pre-compile-test,-pre-compile-test-single">
+        <fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail>
+        <j2seproject3:javac srcdir="" destdir="${build.test.classes.dir}" debug="true" classpath="${javac.test.classpath}">
+            <customize>
+                <patternset includes="${javac.includes}"/>
+            </customize>
+        </j2seproject3:javac>
+        <copy todir="${build.test.classes.dir}"/>
+    </target>
+    <target name="-post-compile-test-single">
+        <!-- Empty placeholder for easier customization. -->
+        <!-- You can override this target in the ../build.xml file. -->
+    </target>
+    <target name="compile-test-single" depends="init,compile,-pre-pre-compile-test,-pre-compile-test-single,-do-compile-test-single,-post-compile-test-single"/>
+    <!--
+    =======================
+    JUNIT EXECUTION SECTION
+    =======================
+    -->
+    <target name="-pre-test-run" if="have.tests" depends="init">
+        <mkdir dir="${build.test.results.dir}"/>
+    </target>
+    <target name="-do-test-run" if="have.tests" depends="init,compile-test,-pre-test-run">
+        <j2seproject3:junit/>
+    </target>
+    <target name="-post-test-run" if="have.tests" depends="init,compile-test,-pre-test-run,-do-test-run">
+        <fail if="tests.failed">Some tests failed; see details above.</fail>
+    </target>
+    <target name="test-report" if="have.tests" depends="init"/>
+    <target name="-test-browse" if="netbeans.home+have.tests" depends="init"/>
+    <target name="test" depends="init,compile-test,-pre-test-run,-do-test-run,test-report,-post-test-run,-test-browse" description="Run unit tests."/>
+    <target name="-pre-test-run-single" if="have.tests" depends="init">
+        <mkdir dir="${build.test.results.dir}"/>
+    </target>
+    <target name="-do-test-run-single" if="have.tests" depends="init,compile-test-single,-pre-test-run-single">
+        <fail unless="test.includes">Must select some files in the IDE or set test.includes</fail>
+        <j2seproject3:junit includes="${test.includes}"/>
+    </target>
+    <target name="-post-test-run-single" if="have.tests" depends="init,compile-test-single,-pre-test-run-single,-do-test-run-single">
+        <fail if="tests.failed">Some tests failed; see details above.</fail>
+    </target>
+    <target name="test-single" depends="init,compile-test-single,-pre-test-run-single,-do-test-run-single,-post-test-run-single" description="Run single unit test."/>
+    <!--
+    =======================
+    JUNIT DEBUGGING SECTION
+    =======================
+    -->
+    <target name="-debug-start-debuggee-test" if="have.tests" depends="init,compile-test">
+        <fail unless="test.class">Must select one file in the IDE or set test.class</fail>
+        <j2seproject3:debug classname="junit.textui.TestRunner" classpath="${debug.test.classpath}">
+            <customize>
+                <arg line="${test.class}"/>
+            </customize>
+        </j2seproject3:debug>
+    </target>
+    <target name="-debug-start-debugger-test" if="netbeans.home+have.tests" depends="init,compile-test">
+        <j2seproject1:nbjpdastart name="${test.class}" classpath="${debug.test.classpath}"/>
+    </target>
+    <target name="debug-test" depends="init,compile-test,-debug-start-debugger-test,-debug-start-debuggee-test"/>
+    <target name="-do-debug-fix-test" if="netbeans.home" depends="init,-pre-debug-fix,compile-test-single">
+        <j2seproject1:nbjpdareload dir="${build.test.classes.dir}"/>
+    </target>
+    <target name="debug-fix-test" if="netbeans.home" depends="init,-pre-debug-fix,-do-debug-fix-test"/>
+    <!--
+    =========================
+    APPLET EXECUTION SECTION
+    =========================
+    -->
+    <target name="run-applet" depends="init,compile-single">
+        <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 name="-debug-start-debuggee-applet" if="netbeans.home" depends="init,compile-single">
+        <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 name="debug-applet" if="netbeans.home" depends="init,compile-single,-debug-start-debugger,-debug-start-debuggee-applet"/>
+    <!--
+    ===============
+    CLEANUP SECTION
+    ===============
+    -->
+    <target name="deps-clean" depends="init" unless="no.deps">
+        <ant target="clean" inheritall="false" antfile="${project.JSearchClient}/build.xml"/>
+        <ant target="clean" inheritall="false" antfile="${project.JavaHelp}/build.xml"/>
+    </target>
+    <target name="-do-clean" depends="init">
+        <delete dir="${build.dir}"/>
+        <delete dir="${dist.dir}"/>
+    </target>
+    <target name="-post-clean">
+        <!-- Empty placeholder for easier customization. -->
+        <!-- You can override this target in the ../build.xml file. -->
+    </target>
+    <target name="clean" depends="init,deps-clean,-do-clean,-post-clean" description="Clean build products."/>
+</project>
diff --git a/JSearchIndexer_nbproject/nbproject/genfiles.properties b/JSearchIndexer_nbproject/nbproject/genfiles.properties
new file mode 100644
index 0000000000000000000000000000000000000000..aaa2ff465fe29bf7f4e24c299979e4b5a91fc98d
--- /dev/null
+++ b/JSearchIndexer_nbproject/nbproject/genfiles.properties
@@ -0,0 +1,8 @@
+build.xml.data.CRC32=bb874861
+build.xml.script.CRC32=615eaab7
+build.xml.stylesheet.CRC32=a12b3d02
+# 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=bb874861
+nbproject/build-impl.xml.script.CRC32=cce01068
+nbproject/build-impl.xml.stylesheet.CRC32=2093e0f1
diff --git a/JSearchIndexer_nbproject/nbproject/project.properties b/JSearchIndexer_nbproject/nbproject/project.properties
new file mode 100644
index 0000000000000000000000000000000000000000..40f127f6afb9d13338e9c2a4460718d7c4a1282d
--- /dev/null
+++ b/JSearchIndexer_nbproject/nbproject/project.properties
@@ -0,0 +1,83 @@
+# Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+# 
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.  Sun designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Sun in the LICENSE file that accompanied this code.
+# 
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+# 
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+# 
+# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+# CA 95054 USA or visit www.sun.com if you need additional information or
+# have any questions.
+build.classes.dir=${build.dir}/classes
+build.classes.excludes=**/*.java,**/*.form,**/*.html,GNUmakefile
+# This directory is removed when the project is cleaned:
+build.dir=build
+build.generated.dir=${build.dir}/generated
+# 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
+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}/jsearch-indexer.jar
+dist.javadoc.dir=${dist.dir}/javadoc
+file.reference.JSearch-indexer=../jhMaster/JSearch/indexer
+jar.compress=false
+javac.classpath=\
+    ${reference.JSearchClient.jar}:\
+    ${reference.JavaHelp.jar}
+# Space-separated list of extra javac options
+javac.compilerargs=
+javac.deprecation=false
+javac.source=1.4
+javac.target=1.4
+javac.test.classpath=\
+    ${javac.classpath}:\
+    ${build.classes.dir}:\
+    ${libs.junit.classpath}
+javadoc.additionalparam=
+javadoc.author=false
+javadoc.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
+platform.active=default_platform
+project.JavaHelp=../javahelp_nbproject
+project.JSearchClient=../JSearchClient_nbproject
+reference.JavaHelp.jar=${project.JavaHelp}/dist/lib/jh-client.jar
+reference.JSearchClient.jar=${project.JSearchClient}/dist/jsearch-client.jar
+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}
+src.dir=${file.reference.JSearch-indexer}
diff --git a/JSearchIndexer_nbproject/nbproject/project.xml b/JSearchIndexer_nbproject/nbproject/project.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e40bc77541084b5911b24156ea38aa728e1deb06
--- /dev/null
+++ b/JSearchIndexer_nbproject/nbproject/project.xml
@@ -0,0 +1,32 @@
+<?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>JSearchIndexer</name>
+            <minimum-ant-version>1.6.5</minimum-ant-version>
+            <source-roots>
+                <root id="src.dir"/>
+            </source-roots>
+            <test-roots/>
+        </data>
+        <references xmlns="http://www.netbeans.org/ns/ant-project-references/1">
+            <reference>
+                <foreign-project>JSearchClient</foreign-project>
+                <artifact-type>jar</artifact-type>
+                <script>build.xml</script>
+                <target>jar</target>
+                <clean-target>clean</clean-target>
+                <id>jar</id>
+            </reference>
+            <reference>
+                <foreign-project>JavaHelp</foreign-project>
+                <artifact-type>jar</artifact-type>
+                <script>build.xml</script>
+                <target>jar</target>
+                <clean-target>clean</clean-target>
+                <id>jar</id>
+            </reference>
+        </references>
+    </configuration>
+</project>
diff --git a/javahelp_nbproject/build.xml b/javahelp_nbproject/build.xml
new file mode 100644
index 0000000000000000000000000000000000000000..c76e88529db92496b2a541d75474ea536c3502c8
--- /dev/null
+++ b/javahelp_nbproject/build.xml
@@ -0,0 +1,239 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2007 Sun Microsystems, Inc.  All Rights Reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Sun designates this
+particular file as subject to the "Classpath" exception as provided
+by Sun in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+CA 95054 USA or visit www.sun.com if you need additional information or
+have any questions.
+ -->
+<project name="JavaHelp" default="release" basedir=".">
+    <description>Builds, tests, and runs the project JavaHelp.</description>
+    <import file="nbproject/build-impl.xml"/>
+    
+    <property name="dist.dir" value="dist/lib"/> <!-- XXX -->
+    
+    <property name="servlet-jar" value="${basedir}/lib/servlet-api.jar"/>
+    <available property="servlet-jar-present" file="${servlet-jar}"/>
+
+    <property name="jsp-jar" value="${basedir}/lib/jsp-api.jar"/>
+    <available property="jsp-jar-present" file="${jsp-jar}"/>
+    
+    <property name="jdic-jar" value="${basedir}/lib/jdic.jar"/>
+    <available property="jdic-jar-present" file="${jdic-jar}"/>
+
+    <property name="tomcat-zip" value="${java.io.tmpdir}/apache-tomcat-5.5.20.zip"/>
+    <available property="tomcat-zip-present" file="${tomcat-zip}"/>
+
+    <property name="jdic-zip" value="${java.io.tmpdir}/jdic-0.8.4.1-bin-windows.zip"/>
+    <available property="jdic-zip-present" file="${jdic-zip}"/>
+    
+    <target name="-pre-init" 
+        depends="unpack-servlet-jar,unpack-jsp-jar,unpack-jdic-jar"/>
+        
+    <target name="release" description="Build the full JavaHelp JARs" 
+            depends="build-jsearch-jars,copy-jsearch-jars,create-javahelp-jars"/>
+            
+            
+    <target name="release-source" description="Build the source zip file">
+        <property name="version" value="2.0.05"/>
+        <mkdir dir="dist"/>
+        <zip destfile="dist/javahelp2-src-${version}.zip" filesonly="true">
+            <zipfileset dir=".." prefix="javahelp2-${version}">
+                <and>
+                    <filename name="**/*"/>
+                    <none>
+                        <filename name="**/dist/**/*"/>
+                        <filename name="**/build/**/*"/>
+                        <filename name="www/**/*"/>
+                        <filename name="**/*.jar"/>
+                        <filename name="**/*.zip"/>
+                    </none>
+                    <or>
+                        <contains text="GNU General Public License"/>
+                        <filename name="**/nbproject/*.xml"/>
+                        <filename name="**/nbproject/*.properties"/>
+                        <filename name="**/manifest.mf"/>
+                        <filename name="jhMaster/JavaHelp/javahelp/bin/jhindexer"/>
+                        <filename name="jhMaster/JavaHelp/javahelp/bin/jhsearch"/>
+                     </or>
+                </and>
+            </zipfileset>
+        </zip>
+    </target>
+            
+    <target name="unpack-servlet-jar" unless="servlet-jar-present" depends="download-tomcat-zip">
+        <echo message="Unpacking ${tomcat-zip}"/>
+        <unzip src="${tomcat-zip}" dest="${java.io.tmpdir}/"/>
+        <copy failonerror="true" file="${java.io.tmpdir}/apache-tomcat-5.5.20/common/lib/servlet-api.jar"
+            tofile="${servlet-jar}"/>
+    </target>
+    
+    <target name="unpack-jsp-jar" depends="download-tomcat-zip" unless="jsp-jar-present">
+        <echo message="Copying ${jsp-jar}"/>
+        <copy failonerror="true" file="${java.io.tmpdir}/apache-tomcat-5.5.20/common/lib/jsp-api.jar"
+            tofile="${jsp-jar}"/>
+    </target>
+    
+    <target name="download-tomcat-zip" unless="tomcat-zip-present">
+        <echo message="Downloading Apache Tomcat for servlet-api.jar and jsp-api.jar"/>
+        <get src="http://archive.apache.org/dist/tomcat/tomcat-5/v5.5.20/bin/apache-tomcat-5.5.20.zip"
+            dest="${tomcat-zip}"/>
+    </target>
+    
+    <target name="unpack-jdic-jar" description="Download JDIC Jar" unless="jdic-jar-present" 
+            depends="download-jdic-zip">                
+        <unzip src="${jdic-zip}" dest="${java.io.tmpdir}"/>
+        <copy failonerror="true" file="${java.io.tmpdir}/jdic-0.8.4.1-bin-windows/jdic.jar"
+            tofile="${jdic-jar}"/>
+    </target>
+    
+    <target name="download-jdic-zip" unless="jdic-zip-present">
+        <echo>
+Downloading JDIC.  If you get an error like 'Server redirected too many times' download it manually from
+https://jdic.dev.java.net/servlets/ProjectDocumentView?documentID=5715&amp;showInfo=true 
+Then copy the zip file to ${jdic-zip} and re-build
+        </echo>
+        <get src="https://jdic.dev.java.net/files/documents/880/5715/jdic-0.8.4.1-bin-windows.zip"
+            dest="${jdic-zip}"/>
+    </target>
+
+    <target name="build-jsearch-jars">
+        <ant inheritall="false" inheritrefs="false" 
+            antfile="${basedir}/../JSearchIndexer_nbproject/build.xml" target="jar"/>
+        <ant inheritall="false" inheritrefs="false" 
+            antfile="${basedir}/../JSearchClient_nbproject/build.xml" target="jar"/>
+        <delete file="../JSearchIndexer_nbproject/BUILD_LOCK"/>
+    </target>
+    
+    <target name="copy-jsearch-jars">
+        <property name="jsearch-client-jar" value="../JSearchClient_nbproject/dist/jsearch-client.jar"/>
+        <available property="jsearch-client-jar-present" file="${jsearch-client-jar}"/>
+
+        <property name="jsearch-indexer-jar" value="../JSearchIndexer_nbproject/dist/jsearch-indexer.jar"/>
+        <available property="jsearch-indexer-jar-present" file="${jsearch-client-jar}"/>
+
+        <property name="jsearch-jar" value="../JSearchIndexer_nbproject/dist/jsearch.jar"/>
+        <available property="jsearch-jar-present" file="${jsearch-jar}"/>
+
+        <property name="jsearch-misc-jar" value="../JSearchIndexer_nbproject/dist/jsearch-misc.jar"/>
+        <available property="jsearch-misc-jar-present" file="${jsearch-misc-jar}"/>
+        
+        <fail unless="jsearch-client-jar-present" message="${jsearch-client-jar} missing.  Build JSearchIndexer and JSearchClient first."/>
+        <fail unless="jsearch-indexer-jar-present" message="${jsearch-indexer-jar} missing.  Build JSearchIndexer and JSearchClient first."/>
+        <fail unless="jsearch-misc-jar-present" message="${jsearch-misc-jar} missing.  Build JSearchIndexer and JSearchClient first."/>
+        <fail unless="jsearch-jar-present" message="${jsearch-jar} missing.  Build JSearchIndexer and JSearchClient first."/>
+        
+        <copy file="${jsearch-indexer-jar}" tofile="${dist.dir}/jsearch-indexer.jar"/>
+        <copy file="${jsearch-client-jar}" tofile="${dist.dir}/jsearch-client.jar"/>
+        <copy file="${jsearch-misc-jar}" tofile="${dist.dir}/jsearch-misc.jar"/>
+        <copy file="${jsearch-jar}" tofile="${dist.dir}/jsearch.jar"/>
+    </target>
+    
+    <target name="create-javahelp-jars">
+        <delete file="${dist.dir}/jhbasic.jar"/>
+        <jar jarfile="${dist.dir}/jhbasic.jar" manifest="manifest.mf">
+            <fileset dir="${basedir}/build/classes">
+                <include name="**/*"/>
+                <exclude name="**/package.html"/>
+                <exclude name="javax/help/plaf/basic/BasicSearch*.class"/>
+                <exclude name="javax/help/search/**"/>
+                <include name="javax/help/tagext/NavigatorsTEI.class"/>
+                <exclude name="javax/help/SearchHit.class"/>
+                <exclude name="javax/help/SearchTOC*.class"/>
+                <exclude name="javax/help/JHelpSearchNavigator.class"/>
+            </fileset>
+        </jar>
+        
+        <delete file="${dist.dir}/jh.jar"/>
+        <jar jarfile="${dist.dir}/jh.jar" manifest="manifest.mf">
+            <fileset dir="${basedir}/build/classes">
+                <include name="**/*"/>
+                <exclude name="**/package.html"/>
+            </fileset>
+            <fileset dir="${basedir}/../JSearchClient_nbproject/build/classes">
+                <include name="com/sun/java/help/search/**"/>
+                <exclude name="**/package.html"/>
+            </fileset>
+        </jar>
+        
+        <copy todir="${basedir}/build/allclasses">
+            <fileset dir="${basedir}/build/classes">
+                <include name="**/*"/>
+                <exclude name="**/package.html"/>
+            </fileset>
+            <fileset dir="${basedir}/../JSearchClient_nbproject/build/classes">
+                <include name="com/sun/java/help/search/**"/>
+                <exclude name="**/package.html"/>
+            </fileset>
+            <fileset dir="${basedir}/../JSearchIndexer_nbproject/build/classes">
+                <include name="*/**"/>
+                <exclude name="**/package.html"/>
+            </fileset>
+        </copy>
+        
+        <jar jarfile="${dist.dir}/jhall.jar" manifest="manifest.mf">
+            <fileset dir="${basedir}/build/allclasses">
+                <include name="**/*"/>
+            </fileset>
+        </jar>
+        
+        <mkdir dir="${dist.dir}/../bin"/>
+        <copy todir="${dist.dir}/../bin">
+            <fileset dir="${basedir}/../jhMaster/JavaHelp/javahelp/bin">
+                <include name="**"/>
+            </fileset>
+        </copy>
+        
+        <jar jarfile="${dist.dir}/../bin/jhindexer.jar">
+            <manifest>
+                <attribute name="Class-Path" value="../lib/jhall.jar"/>
+                <attribute name="Main-Class" value="com.sun.java.help.search.Indexer"/>
+            </manifest>
+        </jar>
+        
+        <jar jarfile="${dist.dir}/../bin/jhsearch.jar">
+            <manifest>
+                <attribute name="Class-Path" value="../lib/jhall.jar"/>
+                <attribute name="Main-Class" value="com.sun.java.help.search.QueryEngine"/>
+            </manifest>
+        </jar>
+    </target>
+
+    <available property="post.clean.needed" file="${basedir}/build/allclasses"/>
+    <target name="-post-clean" if="post.clean.needed">
+        <delete dir="dist"/>
+        <delete dir="${basedir}/build/allclasses"/>
+        <subant target="clean">
+            <dirset dir="..">
+                <include name="JSearchClient_nbproject"/>
+                <include name="JSearchIndexer_nbproject"/>
+            </dirset>
+        </subant>
+    </target>
+    
+    <target name="-post-jar">
+        <echo>
+
+            
+To build the entire javahelp distribution, run the "release" ant target.
+
+        </echo>
+    </target>
+</project>
diff --git a/javahelp_nbproject/build.xml.orig b/javahelp_nbproject/build.xml.orig
new file mode 100644
index 0000000000000000000000000000000000000000..c99d3f5baeaa921cbb428f68ab0fd8ad35a94a1b
--- /dev/null
+++ b/javahelp_nbproject/build.xml.orig
@@ -0,0 +1,237 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2007 Sun Microsystems, Inc.  All Rights Reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Sun designates this
+particular file as subject to the "Classpath" exception as provided
+by Sun in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+CA 95054 USA or visit www.sun.com if you need additional information or
+have any questions.
+ -->
+<project name="JavaHelp" default="release" basedir=".">
+    <description>Builds, tests, and runs the project JavaHelp.</description>
+    <import file="nbproject/build-impl.xml"/>
+    
+    <property name="dist.dir" value="dist/lib"/> <!-- XXX -->
+    
+    <property name="servlet-jar" value="${basedir}/lib/servlet-api.jar"/>
+    <available property="servlet-jar-present" file="${servlet-jar}"/>
+
+    <property name="jsp-jar" value="${basedir}/lib/jsp-api.jar"/>
+    <available property="jsp-jar-present" file="${jsp-jar}"/>
+    
+    <property name="jdic-jar" value="${basedir}/lib/jdic.jar"/>
+    <available property="jdic-jar-present" file="${jdic-jar}"/>
+
+    <property name="tomcat-zip" value="${java.io.tmpdir}/apache-tomcat-5.5.20.zip"/>
+    <available property="tomcat-zip-present" file="${tomcat-zip}"/>
+
+    <property name="jdic-zip" value="${java.io.tmpdir}/jdic-0.8.4.1-bin-windows.zip"/>
+    <available property="jdic-zip-present" file="${jdic-zip}"/>
+    
+    <target name="-pre-init" 
+        depends="unpack-servlet-jar,unpack-jsp-jar,unpack-jdic-jar"/>
+        
+    <target name="release" description="Build the full JavaHelp JARs" 
+            depends="build-jsearch-jars,copy-jsearch-jars,create-javahelp-jars"/>
+            
+            
+    <target name="release-source" description="Build the source zip file">
+        <property name="version" value="2.0.05"/>
+        <mkdir dir="dist"/>
+        <zip destfile="dist/javahelp2-src-${version}.zip" filesonly="true">
+            <zipfileset dir=".." prefix="javahelp2-${version}">
+                <and>
+                    <filename name="**/*"/>
+                    <none>
+                        <filename name="**/dist/**/*"/>
+                        <filename name="**/build/**/*"/>
+                        <filename name="www/**/*"/>
+                        <filename name="**/*.jar"/>
+                        <filename name="**/*.zip"/>
+                    </none>
+                    <or>
+                        <contains text="GNU General Public License"/>
+                        <filename name="**/nbproject/*.xml"/>
+                        <filename name="**/nbproject/*.properties"/>
+                        <filename name="**/manifest.mf"/>
+                    </or>
+                </and>
+            </zipfileset>
+        </zip>
+    </target>
+            
+    <target name="unpack-servlet-jar" unless="servlet-jar-present" depends="download-tomcat-zip">
+        <echo message="Unpacking ${tomcat-zip}"/>
+        <unzip src="${tomcat-zip}" dest="${java.io.tmpdir}/"/>
+        <copy failonerror="true" file="${java.io.tmpdir}/apache-tomcat-5.5.20/common/lib/servlet-api.jar"
+            tofile="${servlet-jar}"/>
+    </target>
+    
+    <target name="unpack-jsp-jar" depends="download-tomcat-zip" unless="jsp-jar-present">
+        <echo message="Copying ${jsp-jar}"/>
+        <copy failonerror="true" file="${java.io.tmpdir}/apache-tomcat-5.5.20/common/lib/jsp-api.jar"
+            tofile="${jsp-jar}"/>
+    </target>
+    
+    <target name="download-tomcat-zip" unless="tomcat-zip-present">
+        <echo message="Downloading Apache Tomcat for servlet-api.jar and jsp-api.jar"/>
+        <get src="http://archive.apache.org/dist/tomcat/tomcat-5/v5.5.20/bin/apache-tomcat-5.5.20.zip"
+            dest="${tomcat-zip}"/>
+    </target>
+    
+    <target name="unpack-jdic-jar" description="Download JDIC Jar" unless="jdic-jar-present" 
+            depends="download-jdic-zip">                
+        <unzip src="${jdic-zip}" dest="${java.io.tmpdir}"/>
+        <copy failonerror="true" file="${java.io.tmpdir}/jdic-0.8.4.1-bin-windows/jdic.jar"
+            tofile="${jdic-jar}"/>
+    </target>
+    
+    <target name="download-jdic-zip" unless="jdic-zip-present">
+        <echo>
+Downloading JDIC.  If you get an error like 'Server redirected too many times' download it manually from
+https://jdic.dev.java.net/servlets/ProjectDocumentView?documentID=5715&amp;showInfo=true 
+Then copy the zip file to ${jdic-zip} and re-build
+        </echo>
+        <get src="https://jdic.dev.java.net/files/documents/880/5715/jdic-0.8.4.1-bin-windows.zip"
+            dest="${jdic-zip}"/>
+    </target>
+
+    <target name="build-jsearch-jars">
+        <ant inheritall="false" inheritrefs="false" 
+            antfile="${basedir}/../JSearchIndexer_nbproject/build.xml" target="jar"/>
+        <ant inheritall="false" inheritrefs="false" 
+            antfile="${basedir}/../JSearchClient_nbproject/build.xml" target="jar"/>
+        <delete file="../JSearchIndexer_nbproject/BUILD_LOCK"/>
+    </target>
+    
+    <target name="copy-jsearch-jars">
+        <property name="jsearch-client-jar" value="../JSearchClient_nbproject/dist/jsearch-client.jar"/>
+        <available property="jsearch-client-jar-present" file="${jsearch-client-jar}"/>
+
+        <property name="jsearch-indexer-jar" value="../JSearchIndexer_nbproject/dist/jsearch-indexer.jar"/>
+        <available property="jsearch-indexer-jar-present" file="${jsearch-client-jar}"/>
+
+        <property name="jsearch-jar" value="../JSearchIndexer_nbproject/dist/jsearch.jar"/>
+        <available property="jsearch-jar-present" file="${jsearch-jar}"/>
+
+        <property name="jsearch-misc-jar" value="../JSearchIndexer_nbproject/dist/jsearch-misc.jar"/>
+        <available property="jsearch-misc-jar-present" file="${jsearch-misc-jar}"/>
+        
+        <fail unless="jsearch-client-jar-present" message="${jsearch-client-jar} missing.  Build JSearchIndexer and JSearchClient first."/>
+        <fail unless="jsearch-indexer-jar-present" message="${jsearch-indexer-jar} missing.  Build JSearchIndexer and JSearchClient first."/>
+        <fail unless="jsearch-misc-jar-present" message="${jsearch-misc-jar} missing.  Build JSearchIndexer and JSearchClient first."/>
+        <fail unless="jsearch-jar-present" message="${jsearch-jar} missing.  Build JSearchIndexer and JSearchClient first."/>
+        
+        <copy file="${jsearch-indexer-jar}" tofile="${dist.dir}/jsearch-indexer.jar"/>
+        <copy file="${jsearch-client-jar}" tofile="${dist.dir}/jsearch-client.jar"/>
+        <copy file="${jsearch-misc-jar}" tofile="${dist.dir}/jsearch-misc.jar"/>
+        <copy file="${jsearch-jar}" tofile="${dist.dir}/jsearch.jar"/>
+    </target>
+    
+    <target name="create-javahelp-jars">
+        <delete file="${dist.dir}/jhbasic.jar"/>
+        <jar jarfile="${dist.dir}/jhbasic.jar" manifest="manifest.mf">
+            <fileset dir="${basedir}/build/classes">
+                <include name="**/*"/>
+                <exclude name="**/package.html"/>
+                <exclude name="javax/help/plaf/basic/BasicSearch*.class"/>
+                <exclude name="javax/help/search/**"/>
+                <include name="javax/help/tagext/NavigatorsTEI.class"/>
+                <exclude name="javax/help/SearchHit.class"/>
+                <exclude name="javax/help/SearchTOC*.class"/>
+                <exclude name="javax/help/JHelpSearchNavigator.class"/>
+            </fileset>
+        </jar>
+        
+        <delete file="${dist.dir}/jh.jar"/>
+        <jar jarfile="${dist.dir}/jh.jar" manifest="manifest.mf">
+            <fileset dir="${basedir}/build/classes">
+                <include name="**/*"/>
+                <exclude name="**/package.html"/>
+            </fileset>
+            <fileset dir="${basedir}/../JSearchClient_nbproject/build/classes">
+                <include name="com/sun/java/help/search/**"/>
+                <exclude name="**/package.html"/>
+            </fileset>
+        </jar>
+        
+        <copy todir="${basedir}/build/allclasses">
+            <fileset dir="${basedir}/build/classes">
+                <include name="**/*"/>
+                <exclude name="**/package.html"/>
+            </fileset>
+            <fileset dir="${basedir}/../JSearchClient_nbproject/build/classes">
+                <include name="com/sun/java/help/search/**"/>
+                <exclude name="**/package.html"/>
+            </fileset>
+            <fileset dir="${basedir}/../JSearchIndexer_nbproject/build/classes">
+                <include name="*/**"/>
+                <exclude name="**/package.html"/>
+            </fileset>
+        </copy>
+        
+        <jar jarfile="${dist.dir}/jhall.jar" manifest="manifest.mf">
+            <fileset dir="${basedir}/build/allclasses">
+                <include name="**/*"/>
+            </fileset>
+        </jar>
+        
+        <mkdir dir="${dist.dir}/../bin"/>
+        <copy todir="${dist.dir}/../bin">
+            <fileset dir="${basedir}/../jhMaster/JavaHelp/javahelp/bin">
+                <include name="**"/>
+            </fileset>
+        </copy>
+        
+        <jar jarfile="${dist.dir}/../bin/jhindexer.jar">
+            <manifest>
+                <attribute name="Class-Path" value="../lib/jhall.jar"/>
+                <attribute name="Main-Class" value="com.sun.java.help.search.Indexer"/>
+            </manifest>
+        </jar>
+        
+        <jar jarfile="${dist.dir}/../bin/jhsearch.jar">
+            <manifest>
+                <attribute name="Class-Path" value="../lib/jhall.jar"/>
+                <attribute name="Main-Class" value="com.sun.java.help.search.QueryEngine"/>
+            </manifest>
+        </jar>
+    </target>
+
+    <available property="post.clean.needed" file="${basedir}/build/allclasses"/>
+    <target name="-post-clean" if="post.clean.needed">
+        <delete dir="dist"/>
+        <delete dir="${basedir}/build/allclasses"/>
+        <subant target="clean">
+            <dirset dir="..">
+                <include name="JSearchClient_nbproject"/>
+                <include name="JSearchIndexer_nbproject"/>
+            </dirset>
+        </subant>
+    </target>
+    
+    <target name="-post-jar">
+        <echo>
+
+            
+To build the entire javahelp distribution, run the "release" ant target.
+
+        </echo>
+    </target>
+</project>
diff --git a/javahelp_nbproject/manifest.mf b/javahelp_nbproject/manifest.mf
new file mode 100644
index 0000000000000000000000000000000000000000..7a00441593f89e502fca7bf31fda5526f5a3c2a0
--- /dev/null
+++ b/javahelp_nbproject/manifest.mf
@@ -0,0 +1,27 @@
+Manifest-Version: 1.0
+Created-By: 1.5.0_08 (Sun Microsystems Inc.)
+Specification-Version: 2.0 
+Specification-Vendor: Sun Microsystems, Inc 
+Implementation-Vendor-Id: com.sun 
+Extension-Name: javax.help
+Implementation-Version: 2.0_03
+Implementation-Vendor: Sun Microsystems, Inc 
+
+Name: javax/help/JHelpContentViewer.class
+Java-Bean: True
+
+Name: javax/help/JHelpTOCNavigator.class
+Java-Bean: True
+
+Name: javax/help/
+Package-Sealed: true
+
+Name: javax/help/JHelpIndexNavigator.class
+Java-Bean: True
+
+Name: javax/help/JHelpSearchNavigator.class
+Java-Bean: True
+
+Name: javax/help/JHelp.class
+Java-Bean: True
+
diff --git a/javahelp_nbproject/nbproject/build-impl.xml b/javahelp_nbproject/nbproject/build-impl.xml
new file mode 100644
index 0000000000000000000000000000000000000000..03d65a6227193534efed9e470a35bfd5429f768b
--- /dev/null
+++ b/javahelp_nbproject/nbproject/build-impl.xml
@@ -0,0 +1,547 @@
+<?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 name="JavaHelp-impl" default="default" basedir=".." xmlns:j2seproject3="http://www.netbeans.org/ns/j2se-project/3" xmlns:j2seproject2="http://www.netbeans.org/ns/j2se-project/2" xmlns:j2seproject1="http://www.netbeans.org/ns/j2se-project/1" xmlns:jaxws="http://www.netbeans.org/ns/jax-ws/1">
+    <target name="default" depends="test,jar,javadoc" description="Build and test whole project."/>
+    <!-- 
+    ======================
+    INITIALIZATION SECTION 
+    ======================
+    -->
+    <target name="-pre-init">
+        <!-- Empty placeholder for easier customization. -->
+        <!-- You can override this target in the ../build.xml file. -->
+    </target>
+    <target name="-init-private" depends="-pre-init">
+        <property file="nbproject/private/config.properties"/>
+        <property file="nbproject/private/configs/${config}.properties"/>
+        <property file="nbproject/private/private.properties"/>
+    </target>
+    <target name="-init-user" depends="-pre-init,-init-private">
+        <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 name="-init-project" depends="-pre-init,-init-private,-init-user">
+        <property file="nbproject/configs/${config}.properties"/>
+        <property file="nbproject/project.properties"/>
+    </target>
+    <target name="-do-init" depends="-pre-init,-init-private,-init-user,-init-project,-init-macrodef-property">
+        <available file="${manifest.file}" property="manifest.available"/>
+        <condition property="manifest.available+main.class">
+            <and>
+                <isset property="manifest.available"/>
+                <isset property="main.class"/>
+                <not>
+                    <equals arg1="${main.class}" arg2="" trim="true"/>
+                </not>
+            </and>
+        </condition>
+        <condition property="manifest.available+main.class+mkdist.available">
+            <and>
+                <istrue value="${manifest.available+main.class}"/>
+                <isset property="libs.CopyLibs.classpath"/>
+            </and>
+        </condition>
+        <condition property="have.tests">
+            <or/>
+        </condition>
+        <condition property="have.sources">
+            <or>
+                <available file="${src.impl.dir}"/>
+                <available file="${src.new.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">
+            <isfalse value="${javadoc.preview}"/>
+        </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=""/>
+    </target>
+    <target name="-post-init">
+        <!-- Empty placeholder for easier customization. -->
+        <!-- You can override this target in the ../build.xml file. -->
+    </target>
+    <target name="-init-check" depends="-pre-init,-init-private,-init-user,-init-project,-do-init">
+        <fail unless="src.impl.dir">Must set src.impl.dir</fail>
+        <fail unless="src.new.dir">Must set src.new.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 name="-init-macrodef-javac">
+        <macrodef name="javac" uri="http://www.netbeans.org/ns/j2se-project/3">
+            <attribute name="srcdir" default="${src.impl.dir}:${src.new.dir}"/>
+            <attribute name="destdir" default="${build.classes.dir}"/>
+            <attribute name="classpath" default="${javac.classpath}"/>
+            <attribute name="debug" default="${javac.debug}"/>
+            <element name="customize" optional="true"/>
+            <sequential>
+                <depend srcdir="@{srcdir}" destdir="@{destdir}" cache="${build.dir}/depcache">
+                    <classpath>
+                        <path path="@{classpath}"/>
+                    </classpath>
+                </depend>
+                <javac srcdir="@{srcdir}" destdir="@{destdir}" debug="@{debug}" deprecation="${javac.deprecation}" source="${javac.source}" target="${javac.target}" includeantruntime="false">
+                    <classpath>
+                        <path path="@{classpath}"/>
+                    </classpath>
+                    <compilerarg line="${javac.compilerargs}"/>
+                    <customize/>
+                </javac>
+            </sequential>
+        </macrodef>
+    </target>
+    <target name="-init-macrodef-junit">
+        <macrodef name="junit" uri="http://www.netbeans.org/ns/j2se-project/3">
+            <attribute name="includes" default="**/*Test.java"/>
+            <sequential>
+                <junit showoutput="true" fork="true" dir="${basedir}" failureproperty="tests.failed" errorproperty="tests.failed">
+                    <batchtest todir="${build.test.results.dir}"/>
+                    <classpath>
+                        <path path="${run.test.classpath}"/>
+                    </classpath>
+                    <syspropertyset>
+                        <propertyref prefix="test-sys-prop."/>
+                        <mapper type="glob" from="test-sys-prop.*" to="*"/>
+                    </syspropertyset>
+                    <formatter type="brief" usefile="false"/>
+                    <formatter type="xml"/>
+                    <jvmarg line="${run.jvmargs}"/>
+                </junit>
+            </sequential>
+        </macrodef>
+    </target>
+    <target name="-init-macrodef-nbjpda">
+        <macrodef name="nbjpdastart" uri="http://www.netbeans.org/ns/j2se-project/1">
+            <attribute name="name" default="${main.class}"/>
+            <attribute name="classpath" default="${debug.classpath}"/>
+            <attribute name="stopclassname" default=""/>
+            <sequential>
+                <nbjpdastart transport="dt_socket" addressproperty="jpda.address" name="@{name}" stopclassname="@{stopclassname}">
+                    <classpath>
+                        <path path="@{classpath}"/>
+                    </classpath>
+                </nbjpdastart>
+            </sequential>
+        </macrodef>
+        <macrodef name="nbjpdareload" uri="http://www.netbeans.org/ns/j2se-project/1">
+            <attribute name="dir" default="${build.classes.dir}"/>
+            <sequential>
+                <nbjpdareload>
+                    <fileset includes="${fix.includes}*.class" dir="@{dir}"/>
+                </nbjpdareload>
+            </sequential>
+        </macrodef>
+    </target>
+    <target name="-init-macrodef-debug">
+        <macrodef name="debug" uri="http://www.netbeans.org/ns/j2se-project/3">
+            <attribute name="classname" default="${main.class}"/>
+            <attribute name="classpath" default="${debug.classpath}"/>
+            <element name="customize" optional="true"/>
+            <sequential>
+                <java fork="true" classname="@{classname}" dir="${work.dir}">
+                    <jvmarg value="-Xdebug"/>
+                    <jvmarg value="-Xnoagent"/>
+                    <jvmarg value="-Djava.compiler=none"/>
+                    <jvmarg value="-Xrunjdwp:transport=dt_socket,address=${jpda.address}"/>
+                    <jvmarg line="${run.jvmargs}"/>
+                    <classpath>
+                        <path path="@{classpath}"/>
+                    </classpath>
+                    <syspropertyset>
+                        <propertyref prefix="run-sys-prop."/>
+                        <mapper type="glob" from="run-sys-prop.*" to="*"/>
+                    </syspropertyset>
+                    <customize/>
+                </java>
+            </sequential>
+        </macrodef>
+    </target>
+    <target name="-init-macrodef-java">
+        <macrodef name="java" uri="http://www.netbeans.org/ns/j2se-project/1">
+            <attribute name="classname" default="${main.class}"/>
+            <element name="customize" optional="true"/>
+            <sequential>
+                <java fork="true" classname="@{classname}" dir="${work.dir}">
+                    <jvmarg line="${run.jvmargs}"/>
+                    <classpath>
+                        <path path="${run.classpath}"/>
+                    </classpath>
+                    <syspropertyset>
+                        <propertyref prefix="run-sys-prop."/>
+                        <mapper type="glob" from="run-sys-prop.*" to="*"/>
+                    </syspropertyset>
+                    <customize/>
+                </java>
+            </sequential>
+        </macrodef>
+    </target>
+    <target name="-init-presetdef-jar">
+        <presetdef name="jar" uri="http://www.netbeans.org/ns/j2se-project/1">
+            <jar jarfile="${dist.jar}" compress="${jar.compress}">
+                <j2seproject1:fileset dir="${build.classes.dir}"/>
+            </jar>
+        </presetdef>
+    </target>
+    <target name="init" 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"/>
+    <!--
+    ===================
+    COMPILATION SECTION
+    ===================
+    -->
+    <target name="deps-jar" depends="init" unless="no.deps"/>
+    <target name="-pre-pre-compile" depends="init,deps-jar">
+        <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 name="-do-compile" depends="init,deps-jar,-pre-pre-compile,-pre-compile" if="have.sources">
+        <j2seproject3:javac/>
+        <copy todir="${build.classes.dir}">
+            <fileset dir="${src.impl.dir}" excludes="${build.classes.excludes}"/>
+            <fileset dir="${src.new.dir}" excludes="${build.classes.excludes}"/>
+        </copy>
+    </target>
+    <target name="-post-compile">
+        <!-- Empty placeholder for easier customization. -->
+        <!-- You can override this target in the ../build.xml file. -->
+    </target>
+    <target name="compile" depends="init,deps-jar,-pre-pre-compile,-pre-compile,-do-compile,-post-compile" description="Compile project."/>
+    <target name="-pre-compile-single">
+        <!-- Empty placeholder for easier customization. -->
+        <!-- You can override this target in the ../build.xml file. -->
+    </target>
+    <target name="-do-compile-single" depends="init,deps-jar,-pre-pre-compile">
+        <fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail>
+        <j2seproject3:javac>
+            <customize>
+                <patternset includes="${javac.includes}"/>
+            </customize>
+        </j2seproject3:javac>
+    </target>
+    <target name="-post-compile-single">
+        <!-- Empty placeholder for easier customization. -->
+        <!-- You can override this target in the ../build.xml file. -->
+    </target>
+    <target name="compile-single" depends="init,deps-jar,-pre-pre-compile,-pre-compile-single,-do-compile-single,-post-compile-single"/>
+    <!--
+    ====================
+    JAR BUILDING SECTION
+    ====================
+    -->
+    <target name="-pre-pre-jar" depends="init">
+        <dirname property="dist.jar.dir" file="${dist.jar}"/>
+        <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 name="-do-jar-without-manifest" depends="init,compile,-pre-pre-jar,-pre-jar" unless="manifest.available">
+        <j2seproject1:jar/>
+    </target>
+    <target name="-do-jar-with-manifest" depends="init,compile,-pre-pre-jar,-pre-jar" if="manifest.available" unless="manifest.available+main.class">
+        <j2seproject1:jar manifest="${manifest.file}"/>
+    </target>
+    <target name="-do-jar-with-mainclass" depends="init,compile,-pre-pre-jar,-pre-jar" if="manifest.available+main.class" 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>To run this application from the command line without Ant, try:</echo>
+        <property name="build.classes.dir.resolved" location="${build.classes.dir}"/>
+        <property name="dist.jar.resolved" location="${dist.jar}"/>
+        <pathconvert property="run.classpath.with.dist.jar">
+            <path path="${run.classpath}"/>
+            <map from="${build.classes.dir.resolved}" to="${dist.jar.resolved}"/>
+        </pathconvert>
+        <echo>java -cp "${run.classpath.with.dist.jar}" ${main.class}</echo>
+    </target>
+    <target name="-do-jar-with-libraries" depends="init,compile,-pre-pre-jar,-pre-jar" if="manifest.available+main.class+mkdist.available">
+        <property name="build.classes.dir.resolved" location="${build.classes.dir}"/>
+        <pathconvert property="run.classpath.without.build.classes.dir">
+            <path path="${run.classpath}"/>
+            <map from="${build.classes.dir.resolved}" to=""/>
+        </pathconvert>
+        <pathconvert property="jar.classpath" pathsep=" ">
+            <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" name="copylibs" classpath="${libs.CopyLibs.classpath}"/>
+        <copylibs manifest="${manifest.file}" runtimeclasspath="${run.classpath.without.build.classes.dir}" jarfile="${dist.jar}" compress="${jar.compress}">
+            <fileset dir="${build.classes.dir}"/>
+            <manifest>
+                <attribute name="Main-Class" value="${main.class}"/>
+                <attribute name="Class-Path" value="${jar.classpath}"/>
+            </manifest>
+        </copylibs>
+        <echo>To run this application from the command line without Ant, try:</echo>
+        <property name="dist.jar.resolved" location="${dist.jar}"/>
+        <echo>java -jar "${dist.jar.resolved}"</echo>
+    </target>
+    <target name="-post-jar">
+        <!-- Empty placeholder for easier customization. -->
+        <!-- You can override this target in the ../build.xml file. -->
+    </target>
+    <target name="jar" 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."/>
+    <!--
+    =================
+    EXECUTION SECTION
+    =================
+    -->
+    <target name="run" depends="init,compile" description="Run a main class.">
+        <j2seproject1:java>
+            <customize>
+                <arg line="${application.args}"/>
+            </customize>
+        </j2seproject1:java>
+    </target>
+    <target name="run-single" depends="init,compile-single">
+        <fail unless="run.class">Must select one file in the IDE or set run.class</fail>
+        <j2seproject1:java classname="${run.class}"/>
+    </target>
+    <!--
+    =================
+    DEBUGGING SECTION
+    =================
+    -->
+    <target name="-debug-start-debugger" if="netbeans.home" depends="init">
+        <j2seproject1:nbjpdastart name="${debug.class}"/>
+    </target>
+    <target name="-debug-start-debuggee" depends="init,compile">
+        <j2seproject3:debug>
+            <customize>
+                <arg line="${application.args}"/>
+            </customize>
+        </j2seproject3:debug>
+    </target>
+    <target name="debug" if="netbeans.home" depends="init,compile,-debug-start-debugger,-debug-start-debuggee" description="Debug project in IDE."/>
+    <target name="-debug-start-debugger-stepinto" if="netbeans.home" depends="init">
+        <j2seproject1:nbjpdastart stopclassname="${main.class}"/>
+    </target>
+    <target name="debug-stepinto" if="netbeans.home" depends="init,compile,-debug-start-debugger-stepinto,-debug-start-debuggee"/>
+    <target name="-debug-start-debuggee-single" if="netbeans.home" depends="init,compile-single">
+        <fail unless="debug.class">Must select one file in the IDE or set debug.class</fail>
+        <j2seproject3:debug classname="${debug.class}"/>
+    </target>
+    <target name="debug-single" if="netbeans.home" depends="init,compile-single,-debug-start-debugger,-debug-start-debuggee-single"/>
+    <target name="-pre-debug-fix" depends="init">
+        <fail unless="fix.includes">Must set fix.includes</fail>
+        <property name="javac.includes" value="${fix.includes}.java"/>
+    </target>
+    <target name="-do-debug-fix" if="netbeans.home" depends="init,-pre-debug-fix,compile-single">
+        <j2seproject1:nbjpdareload/>
+    </target>
+    <target name="debug-fix" if="netbeans.home" depends="init,-pre-debug-fix,-do-debug-fix"/>
+    <!--
+    ===============
+    JAVADOC SECTION
+    ===============
+    -->
+    <target name="-javadoc-build" depends="init">
+        <mkdir dir="${dist.javadoc.dir}"/>
+        <javadoc destdir="${dist.javadoc.dir}" source="${javac.source}" notree="${javadoc.notree}" use="${javadoc.use}" nonavbar="${javadoc.nonavbar}" noindex="${javadoc.noindex}" splitindex="${javadoc.splitindex}" author="${javadoc.author}" version="${javadoc.version}" windowtitle="${javadoc.windowtitle}" private="${javadoc.private}" additionalparam="${javadoc.additionalparam}" failonerror="true" useexternalfile="true">
+            <classpath>
+                <path path="${javac.classpath}"/>
+            </classpath>
+            <sourcepath>
+                <pathelement location="${src.impl.dir}"/>
+                <pathelement location="${src.new.dir}"/>
+            </sourcepath>
+            <packageset dir="${src.impl.dir}" includes="*/**"/>
+            <packageset dir="${src.new.dir}" includes="*/**"/>
+            <fileset dir="${src.impl.dir}" includes="*.java"/>
+            <fileset dir="${src.new.dir}" includes="*.java"/>
+        </javadoc>
+    </target>
+    <target name="-javadoc-browse" if="netbeans.home" unless="no.javadoc.preview" depends="init,-javadoc-build">
+        <nbbrowse file="${dist.javadoc.dir}/index.html"/>
+    </target>
+    <target name="javadoc" depends="init,-javadoc-build,-javadoc-browse" description="Build Javadoc."/>
+    <!--
+    =========================
+    JUNIT COMPILATION SECTION
+    =========================
+    -->
+    <target name="-pre-pre-compile-test" if="have.tests" depends="init,compile">
+        <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 name="-do-compile-test" if="have.tests" depends="init,compile,-pre-pre-compile-test,-pre-compile-test">
+        <j2seproject3:javac srcdir="" destdir="${build.test.classes.dir}" debug="true" classpath="${javac.test.classpath}"/>
+        <copy todir="${build.test.classes.dir}"/>
+    </target>
+    <target name="-post-compile-test">
+        <!-- Empty placeholder for easier customization. -->
+        <!-- You can override this target in the ../build.xml file. -->
+    </target>
+    <target name="compile-test" depends="init,compile,-pre-pre-compile-test,-pre-compile-test,-do-compile-test,-post-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 name="-do-compile-test-single" if="have.tests" depends="init,compile,-pre-pre-compile-test,-pre-compile-test-single">
+        <fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail>
+        <j2seproject3:javac srcdir="" destdir="${build.test.classes.dir}" debug="true" classpath="${javac.test.classpath}">
+            <customize>
+                <patternset includes="${javac.includes}"/>
+            </customize>
+        </j2seproject3:javac>
+        <copy todir="${build.test.classes.dir}"/>
+    </target>
+    <target name="-post-compile-test-single">
+        <!-- Empty placeholder for easier customization. -->
+        <!-- You can override this target in the ../build.xml file. -->
+    </target>
+    <target name="compile-test-single" depends="init,compile,-pre-pre-compile-test,-pre-compile-test-single,-do-compile-test-single,-post-compile-test-single"/>
+    <!--
+    =======================
+    JUNIT EXECUTION SECTION
+    =======================
+    -->
+    <target name="-pre-test-run" if="have.tests" depends="init">
+        <mkdir dir="${build.test.results.dir}"/>
+    </target>
+    <target name="-do-test-run" if="have.tests" depends="init,compile-test,-pre-test-run">
+        <j2seproject3:junit/>
+    </target>
+    <target name="-post-test-run" if="have.tests" depends="init,compile-test,-pre-test-run,-do-test-run">
+        <fail if="tests.failed">Some tests failed; see details above.</fail>
+    </target>
+    <target name="test-report" if="have.tests" depends="init"/>
+    <target name="-test-browse" if="netbeans.home+have.tests" depends="init"/>
+    <target name="test" depends="init,compile-test,-pre-test-run,-do-test-run,test-report,-post-test-run,-test-browse" description="Run unit tests."/>
+    <target name="-pre-test-run-single" if="have.tests" depends="init">
+        <mkdir dir="${build.test.results.dir}"/>
+    </target>
+    <target name="-do-test-run-single" if="have.tests" depends="init,compile-test-single,-pre-test-run-single">
+        <fail unless="test.includes">Must select some files in the IDE or set test.includes</fail>
+        <j2seproject3:junit includes="${test.includes}"/>
+    </target>
+    <target name="-post-test-run-single" if="have.tests" depends="init,compile-test-single,-pre-test-run-single,-do-test-run-single">
+        <fail if="tests.failed">Some tests failed; see details above.</fail>
+    </target>
+    <target name="test-single" depends="init,compile-test-single,-pre-test-run-single,-do-test-run-single,-post-test-run-single" description="Run single unit test."/>
+    <!--
+    =======================
+    JUNIT DEBUGGING SECTION
+    =======================
+    -->
+    <target name="-debug-start-debuggee-test" if="have.tests" depends="init,compile-test">
+        <fail unless="test.class">Must select one file in the IDE or set test.class</fail>
+        <j2seproject3:debug classname="junit.textui.TestRunner" classpath="${debug.test.classpath}">
+            <customize>
+                <arg line="${test.class}"/>
+            </customize>
+        </j2seproject3:debug>
+    </target>
+    <target name="-debug-start-debugger-test" if="netbeans.home+have.tests" depends="init,compile-test">
+        <j2seproject1:nbjpdastart name="${test.class}" classpath="${debug.test.classpath}"/>
+    </target>
+    <target name="debug-test" depends="init,compile-test,-debug-start-debugger-test,-debug-start-debuggee-test"/>
+    <target name="-do-debug-fix-test" if="netbeans.home" depends="init,-pre-debug-fix,compile-test-single">
+        <j2seproject1:nbjpdareload dir="${build.test.classes.dir}"/>
+    </target>
+    <target name="debug-fix-test" if="netbeans.home" depends="init,-pre-debug-fix,-do-debug-fix-test"/>
+    <!--
+    =========================
+    APPLET EXECUTION SECTION
+    =========================
+    -->
+    <target name="run-applet" depends="init,compile-single">
+        <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 name="-debug-start-debuggee-applet" if="netbeans.home" depends="init,compile-single">
+        <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 name="debug-applet" if="netbeans.home" depends="init,compile-single,-debug-start-debugger,-debug-start-debuggee-applet"/>
+    <!--
+    ===============
+    CLEANUP SECTION
+    ===============
+    -->
+    <target name="deps-clean" depends="init" unless="no.deps"/>
+    <target name="-do-clean" depends="init">
+        <delete dir="${build.dir}"/>
+        <delete dir="${dist.dir}"/>
+    </target>
+    <target name="-post-clean">
+        <!-- Empty placeholder for easier customization. -->
+        <!-- You can override this target in the ../build.xml file. -->
+    </target>
+    <target name="clean" depends="init,deps-clean,-do-clean,-post-clean" description="Clean build products."/>
+</project>
diff --git a/javahelp_nbproject/nbproject/genfiles.properties b/javahelp_nbproject/nbproject/genfiles.properties
new file mode 100644
index 0000000000000000000000000000000000000000..b645296f628140f109a4c62c3ba3b1bc23a8ae90
--- /dev/null
+++ b/javahelp_nbproject/nbproject/genfiles.properties
@@ -0,0 +1,8 @@
+build.xml.data.CRC32=bc1e27e0
+build.xml.script.CRC32=079caa17
+build.xml.stylesheet.CRC32=a12b3d02
+# 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=74a01f5f
+nbproject/build-impl.xml.script.CRC32=357bfc33
+nbproject/build-impl.xml.stylesheet.CRC32=2093e0f1
diff --git a/javahelp_nbproject/nbproject/project.properties b/javahelp_nbproject/nbproject/project.properties
new file mode 100644
index 0000000000000000000000000000000000000000..1ce731494ee4e01f60aadd9082d91aaee8ba7129
--- /dev/null
+++ b/javahelp_nbproject/nbproject/project.properties
@@ -0,0 +1,86 @@
+# Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+# 
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.  Sun designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Sun in the LICENSE file that accompanied this code.
+# 
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+# 
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+# 
+# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+# CA 95054 USA or visit www.sun.com if you need additional information or
+# have any questions.
+build.classes.dir=${build.dir}/classes
+build.classes.excludes=**/*.java,**/*.form,**/*.html
+# This directory is removed when the project is cleaned:
+build.dir=build
+build.generated.dir=${build.dir}/generated
+# 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
+debug.classpath=\
+    ${run.classpath}
+debug.test.classpath=\
+    ${run.test.classpath}
+# This directory is removed when the project is cleaned:
+dist.dir=dist/lib
+dist.jar=${dist.dir}/jh-client.jar
+dist.javadoc.dir=${dist.dir}/javadoc
+file.reference.jdic.jar=lib/jdic.jar
+file.reference.jsp-api.jar=lib/jsp-api.jar
+file.reference.servlet-api.jar=lib/servlet-api.jar
+file.reference.space-javahelp=..
+file.reference.src-impl=../jhMaster/JavaHelp/src/impl
+file.reference.src-new=../jhMaster/JavaHelp/src/new
+jar.compress=false
+javac.classpath=\
+    ${file.reference.servlet-api.jar}:\
+    ${file.reference.jsp-api.jar}:\
+    ${file.reference.jdic.jar}
+# Space-separated list of extra javac options
+javac.compilerargs=
+javac.deprecation=false
+javac.source=1.4
+javac.target=1.4
+javac.test.classpath=\
+    ${javac.classpath}:\
+    ${build.classes.dir}:\
+    ${libs.junit.classpath}
+javadoc.additionalparam=
+javadoc.author=false
+javadoc.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
+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}
+src.impl.dir=${file.reference.src-impl}
+src.new.dir=${file.reference.src-new}
diff --git a/javahelp_nbproject/nbproject/project.xml b/javahelp_nbproject/nbproject/project.xml
new file mode 100644
index 0000000000000000000000000000000000000000..9ebc689964053776f61389d5de16cdea61f542d0
--- /dev/null
+++ b/javahelp_nbproject/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>JavaHelp</name>
+            <minimum-ant-version>1.6.5</minimum-ant-version>
+            <source-roots>
+                <root id="src.impl.dir"/>
+                <root id="src.new.dir"/>
+            </source-roots>
+            <test-roots/>
+        </data>
+    </configuration>
+</project>
diff --git a/jhMaster/GNUmakefile b/jhMaster/GNUmakefile
new file mode 100644
index 0000000000000000000000000000000000000000..9622291379ae025a523723643c91d93505eb4140
--- /dev/null
+++ b/jhMaster/GNUmakefile
@@ -0,0 +1,44 @@
+#
+# @(#)GNUmakefile	1.14 06/10/30
+# 
+# Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+# 
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.  Sun designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Sun in the LICENSE file that accompanied this code.
+# 
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+# 
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+# 
+# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+# CA 95054 USA or visit www.sun.com if you need additional information or
+# have any questions.
+#
+
+all:
+	java -fullversion
+	cd JSearch ; $(MAKE) all
+	cd JavaHelp/build ; $(MAKE) all
+	cd JavaHelp/demos ; $(MAKE) all validate
+
+release: all docs
+
+docs:	all
+	cd JavaHelp/build ; $(MAKE) docs
+	cd JavaHelp/doc/jhug; $(MAKE) all
+	cd JavaHelp/doc/public-spec/V2.0; $(MAKE) all
+
+clean:
+	cd JSearch ; $(MAKE) clean
+	cd JavaHelp/build ; $(MAKE) clean
+	cd JavaHelp/demos ; $(MAKE) clean
diff --git a/jhMaster/JSearch/GNUmakefile b/jhMaster/JSearch/GNUmakefile
new file mode 100644
index 0000000000000000000000000000000000000000..b926cbfbbecd071a9a39e77572a6fd1d3092874c
--- /dev/null
+++ b/jhMaster/JSearch/GNUmakefile
@@ -0,0 +1,92 @@
+#
+# @(#)GNUmakefile	1.31 06/10/30
+# 
+# Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+# 
+# This code is free software; you can redistribute it and or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.  Sun designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Sun in the LICENSE file that accompanied this code.
+# 
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+# 
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+# 
+# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+# CA 95054 USA or visit www.sun.com if you need additional information or
+# have any questions.
+#
+
+# This is a bare-bones Makefile just to build the engine from scratch.
+#
+# It should be replaced by a real Makefile.
+
+TOP := $(shell pwd)
+
+ifeq ($(JHHOMEWS),)
+TOP=$(shell pwd)
+JHHOMEWS=$(TOP)/../JavaHelp
+endif
+
+CP=/bin/cp -f
+
+PKG = com/sun/java/help/search
+JARS = 	lib/jsearch-misc.jar \
+	lib/jsearch-client.jar \
+	lib/jsearch-indexer.jar \
+	lib/jsearch.jar
+
+all: lib ${JARS} binaries demos
+
+clean: 
+	rm -rf lib
+	cd client ; $(MAKE) clean
+	cd indexer ; $(MAKE) clean
+	cd misc ; $(MAKE) clean
+
+# simple scripts
+
+binaries: jhindexer jhsearch
+	- chmod a+x jhindexer
+	- chmod a+x jhsearch
+
+# a test case
+
+demos: demos/holidays
+
+demos/holidays:
+	mkdir -p demos/holidays
+	cd demos/holidays ; export to ; to=`pwd` ; \
+	cd ${JHHOMEWS}/demos/hs/holidays ; \
+	tar cFFf - hol | ( cd $${to} ; tar xvf - )
+
+
+## JAR files
+
+lib/jsearch.jar: lib/jsearch-client.jar lib/jsearch-indexer.jar lib/jsearch-misc.jar
+	/bin/csh -f jarinto FORCE lib/jsearch.jar \
+		lib/jsearch-client.jar lib/jsearch-indexer.jar lib/jsearch-misc.jar
+
+lib/jsearch-misc.jar: FORCE
+	cd misc ; $(MAKE) JHHOMEWS=$(JHHOMEWS) jar
+
+lib/jsearch-client.jar: lib/jsearch-misc.jar FORCE
+	cd client ; $(MAKE) jar
+
+lib/jsearch-indexer.jar: lib/jsearch-misc.jar FORCE
+	cd indexer ; $(MAKE) jar
+
+## Directories
+
+lib:
+	mkdir -p lib
+
+FORCE:
diff --git a/jhMaster/JSearch/client/GNUmakefile b/jhMaster/JSearch/client/GNUmakefile
new file mode 100644
index 0000000000000000000000000000000000000000..09ad6f29677bb880b6ad9fef828709ff11a936cb
--- /dev/null
+++ b/jhMaster/JSearch/client/GNUmakefile
@@ -0,0 +1,47 @@
+#
+# @(#)GNUmakefile	1.8 06/10/30
+# 
+# Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+# 
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.  Sun designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Sun in the LICENSE file that accompanied this code.
+# 
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+# 
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+# 
+# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+# CA 95054 USA or visit www.sun.com if you need additional information or
+# have any questions.
+#
+
+CLIENT_SRC := $(shell find . -name 'SCCS*' -prune -o -name '*.java' -print)
+CLIENT_CLASSES=$(CLIENT_SRC:%.java=classes/%.class)
+
+RM=/bin/rm
+
+jar:	../lib/jsearch-client.jar
+
+../lib/jsearch-client.jar: $(CLIENT_CLASSES)
+	cd classes ; \
+	jar cf ../../lib/jsearch-client.jar com
+
+classes/%.class: %.java classes
+	export CLASSPATH ; CLASSPATH=../lib/jsearch-misc.jar:. ; \
+	javac -d classes $<
+
+classes:
+	mkdir classes
+
+clean:
+	$(RM) -rf classes
diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/BitBuffer.java b/jhMaster/JSearch/client/com/sun/java/help/search/BitBuffer.java
new file mode 100644
index 0000000000000000000000000000000000000000..150baa3ebe49c34a7f42d2f8a151bfa6aa5ac71f
--- /dev/null
+++ b/jhMaster/JSearch/client/com/sun/java/help/search/BitBuffer.java
@@ -0,0 +1,177 @@
+/*
+ * @(#)BitBuffer.java	1.6 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @date   2/17/98
+ * @author Jacek R. Ambroziak
+ * @group  Sun Microsystems Laboratories
+ */
+
+/*
+  BitBuffer's client has to stick to a usage protocol:
+  
+  - start with new or cleared BitBuffer
+  - do appends for a while
+  - finish w/ close()
+  
+  */
+
+package com.sun.java.help.search;
+import java.io.*;
+
+class BitBuffer
+{
+  private static final int InitSize   = 256;
+  private static final int NBits      =  32;
+  private static final int BitsInByte =   8;
+  private static final int BytesInInt =   4;
+  
+  private int   _avail = NBits;
+  private int   _word = 0;
+  private int   _free = 0;
+  private int   _size = InitSize;
+  private int[] _array = new int[InitSize];
+
+  public void close()
+  {
+    if (_avail < NBits)
+      store(_word << _avail);
+    else
+      _avail = 0;
+  }
+  
+  public void write(DataOutput out) throws IOException
+  {
+    for (int i = 0; i < _free - 1; i++)
+      out.writeInt(_array[i]);
+    int word = _array[_free - 1];
+    int bytes = BytesInInt - _avail/BitsInByte;
+    int shift = NBits;
+    while (bytes-- > 0)
+      out.writeByte((word >>> (shift -= BitsInByte)) & 0xFF);
+  }
+
+  public void clear()
+  {
+    _word   = 0;
+    _avail  = NBits;
+    _free   = 0;
+  }
+  
+  public int byteCount() {
+    return _free*BytesInInt - _avail/BitsInByte;
+  }
+  
+  public int bitCount() {
+    return NBits*_free - _avail;
+  }
+
+  public void setFrom(BitBuffer rhs)
+  {
+    _word  = rhs._word;
+    _avail = rhs._avail;
+    if ((_free = rhs._free) > _size)
+      _array = new int[_size = rhs._free];
+    System.arraycopy(rhs._array, 0, _array, 0, _free);
+  }
+  
+  private void growArray(int newSize)
+  {
+    int[] newArray = new int[_size = newSize];
+    System.arraycopy(_array, 0, newArray, 0, _free);
+    _array = newArray;
+  }
+
+  private void store(int value)
+  {
+    if (_free == _size)
+      growArray(_size * 2);
+    _array[_free++] = value;
+  }
+
+  public void append(int bit)
+  {
+    _word = (_word << 1) | bit;
+    if (--_avail == 0)
+      {
+	store(_word);
+	_word = 0;
+	_avail = NBits;
+      }
+  }
+  
+  public void append(int source, int kBits)
+  {
+    if (kBits < _avail)
+      {
+	_word = (_word << kBits) | source;
+	_avail -= kBits;
+      }
+    else if (kBits > _avail)
+      {
+	int leftover = kBits - _avail;
+	store((_word << _avail) | (source >>> leftover));
+	_word = source;
+	_avail = NBits - leftover;
+      }
+    else
+      {
+	store((_word << kBits) | source);
+	_word = 0;
+	_avail = NBits;
+      }
+  }
+  
+  public void concatenate(BitBuffer bb)
+  {
+    if (NBits*(_size - _free) + _avail < bb.bitCount())
+      growArray(_free + bb._free + 1);
+
+    if (_avail == 0)
+      {
+	System.arraycopy(bb._array, 0, _array, _free, bb._free);
+	_avail = bb._avail;
+	_free += bb._free;
+      }
+    else
+      {
+	int tp = _free - 1;	// target
+	int sp = 0;		// source
+	do {
+	  _array[tp++] |= bb._array[sp] >>> (NBits - _avail);
+	  _array[tp] = bb._array[sp++] << _avail;
+	}
+	while (sp < bb._free);
+	_free += bb._free;
+	if ((_avail += bb._avail) >= NBits)
+	  {
+	    _avail -= NBits;
+	    _free--;
+	  }
+      }
+  }
+}
diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/Block.java b/jhMaster/JSearch/client/com/sun/java/help/search/Block.java
new file mode 100644
index 0000000000000000000000000000000000000000..6790c6f7874f552b173e77ca659657ce04209574
--- /dev/null
+++ b/jhMaster/JSearch/client/com/sun/java/help/search/Block.java
@@ -0,0 +1,109 @@
+/*
+ * @(#)Block.java	1.10 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @(#) Block.java 1.3 - last change made 03/20/98
+ */
+
+package com.sun.java.help.search;
+
+import java.io.IOException;
+
+/**
+ * This class represents a Block of information in DictBlock
+ *
+ * @author Jacek Ambroziak
+ * @author Roger D. Brinkley
+ * @version	1.3	03/20/98
+ */
+
+class Block
+{
+  public static final int HEADERLEN = 8;
+  public static final int IDLEN = 4;
+  public int number;
+  public boolean isLeaf = true;
+  public int free = 0;
+  public byte[] data = null;
+  
+  public Block(int blocksize) {
+    data = new byte[blocksize - HEADERLEN];
+  }
+
+  public void setBlockNumber(int n) {
+    number = n;
+  }
+
+  public void setFree(int free) {
+    free = free;
+  }
+  
+  public int integerAt(int i) {
+    return ((((((data[i++]&0xFF)<<8)
+	       |data[i++]&0xFF)<<8)
+	     |data[i++]&0xFF)<<8)
+      |data[i]&0xFF;
+  }
+  
+  public void setIntegerAt(int i, int value)
+  {
+    for (int j = i + 3; j >= i; j--, value >>>= 8)
+      data[j] = (byte)(value & 0xFF);
+  }
+
+  public static Block readIn(RAFFile in, Block block)
+    throws IOException
+  {
+    debug("readIn");
+    block.number = in.readInt();
+    int twoFields = in.readInt();
+    block.isLeaf = (twoFields & 0x80000000) != 0;
+    block.free = twoFields & 0x7FFFFFFF;
+    in.readFully(block.data);
+    return block;
+  }
+  
+  public void writeOut(RAFFile out) throws IOException
+  {
+    out.writeInt(number);
+    out.writeInt(free | (isLeaf ? 0x80000000 : 0));
+    out.write(data);
+  }
+
+  /**
+   * Debug code
+   */
+
+  private static boolean debug=false;
+  private static void debug(String msg) {
+    if (debug) {
+      System.err.println("Block: "+msg);
+    }
+  }
+
+}
+
diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/BlockFactory.java b/jhMaster/JSearch/client/com/sun/java/help/search/BlockFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..25864b7705a884be3e73faa9bfcd4ad7328182b5
--- /dev/null
+++ b/jhMaster/JSearch/client/com/sun/java/help/search/BlockFactory.java
@@ -0,0 +1,33 @@
+/*
+ * @(#)BlockFactory.java	1.6 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.java.help.search;
+
+interface BlockFactory
+{
+  public Block makeBlock();
+}
diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/BlockManager.java b/jhMaster/JSearch/client/com/sun/java/help/search/BlockManager.java
new file mode 100644
index 0000000000000000000000000000000000000000..e249c0880e9507e39774e62fecc63bd3c1aa54c0
--- /dev/null
+++ b/jhMaster/JSearch/client/com/sun/java/help/search/BlockManager.java
@@ -0,0 +1,249 @@
+/*
+ * @(#)BlockManager.java	1.14 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @(#) BlockManager.java 1.5 - last change made 03/20/98
+ */
+package com.sun.java.help.search;
+
+import java.io.*;
+
+/**
+ * This class manages Block(s) of information in DictBlock
+ *
+ * @author Jacek R. Ambroziak
+ * @author Roger D. Brinkley
+ * @version	1.5	03/20/98
+ */
+
+class BlockManager
+{
+  /* the Dict file factory. It handles both retrieval and caching. 
+   */
+  private static RAFFileFactory factory = RAFFileFactory.create();
+
+  //!! not sure if the double list is still correct after many changes
+  private class BlockDescriptor
+  {
+    public Block block = null;
+    public boolean lock = false;
+    public boolean modf = false;
+    public int prev = 0;
+    public int next = 0;
+  
+    public void reset()
+    {
+      lock = modf = false;
+      block = null;
+    }
+  }
+
+  private RAFFile file;
+  private long blockSize;
+  private boolean update;
+  final private int         nBlocksLimit = 64;
+  private int              blockTableSize;
+  private BlockDescriptor[] blockTab;
+  private int              nBlocks = 0;
+  private int              oldest = 0;
+  private int              newest = 0;
+  private BlockFactory     bfactory = null;
+  private final static int INCR = 256; // size increment
+  private Block dummy;
+  
+  public BlockManager(BlockManagerParameters params,
+		      boolean update,
+		      BlockFactory bfactory) throws IOException
+  {
+    this.bfactory = bfactory;
+    this.update = update;
+    //    params.readState();
+    blockSize = (long)params.getBlockSize();
+    debug(params.getURL().toString());
+    file = factory.get(params.getURL(), update);
+    debug(file.toString());
+    dummy = bfactory.makeBlock();
+    if (file.length() == 0 && update) {
+      dummy.setBlockNumber(0);
+      writeBlock(dummy);
+    }
+    blockTableSize = (int)(file.length()/blockSize);
+    blockTab = new BlockDescriptor[blockTableSize];
+    mapBlock(0, new BlockDescriptor(), bfactory.makeBlock());
+  }
+  
+  public void lockBlock(int blNum) {
+    blockTab[blNum].lock = true;
+  }
+
+  public void unlockBlock(int blNum) {
+    blockTab[blNum].lock = false;
+  }
+
+  public void setModified(int blNum) {
+    blockTab[blNum].modf = true;
+  }
+
+  public void close() throws IOException
+  {
+    if (update)
+      for (int i = 0; i < blockTableSize; i++)
+	if (blockTab[i] != null && blockTab[i].modf)
+	  writeBlock(blockTab[i].block);
+    file.close();
+  }
+
+  public Block accessBlock(int blockNumber) throws Exception
+  {
+    if (blockTab[blockNumber] != null)
+      moveToFront(blockNumber);
+    else if (nBlocks < nBlocksLimit)
+      mapBlock(blockNumber, new BlockDescriptor(), bfactory.makeBlock());
+    else
+      remapSomeBlock(blockNumber);
+    return blockTab[blockNumber].block;
+  }
+  
+  public Block getNewBlock() throws Exception
+  {
+    int number = (int)(file.length()/blockSize);
+    if (number > blockTableSize - 1)
+      {
+	BlockDescriptor[] newArray =
+	  new BlockDescriptor[blockTableSize + INCR];
+	System.arraycopy(blockTab, 0, newArray, 0, blockTableSize);
+	blockTab = newArray;
+	blockTableSize += INCR;
+      }
+    if (nBlocks < nBlocksLimit)
+      {
+	Block bl = bfactory.makeBlock();
+	bl.setBlockNumber(number);
+	writeBlock(bl);
+	addDescriptor(bl, number, new BlockDescriptor());
+      }
+    else
+      {
+	dummy.setBlockNumber(number);
+	writeBlock(dummy);
+	remapSomeBlock(number);
+      }
+    return blockTab[number].block;
+  }
+
+  private void mapBlock(int blockNumber, BlockDescriptor desc, Block block)
+    throws IOException
+  {
+    file.seek(blockSize * blockNumber);
+    Block.readIn(file, block);
+    addDescriptor(block, blockNumber, desc);
+  }
+  
+  private void addDescriptor(Block block, int blockNumber,
+			     BlockDescriptor desc)
+  {
+    blockTab[blockNumber] = desc;
+    desc.block = block;
+    blockTab[desc.prev = newest].next = blockNumber;
+    newest = blockNumber;
+    nBlocks++;
+  }
+  
+  private void remapSomeBlock(int blockNumber) throws Exception
+  {
+    int index = oldest;
+    while (blockTab[index].lock && index != newest)
+      index = blockTab[index].next;
+    if (blockTab[index].lock)
+      throw new Exception("everything locked");
+    if (blockTab[index].modf)
+      writeBlock(blockTab[index].block);
+    
+    nBlocks--;
+    Block reused = blockTab[index].block;
+    // delete from double-linked list
+    if (index == oldest)
+      oldest = blockTab[index].next;
+    else if (index == newest)
+      newest = blockTab[index].prev;
+    else
+      {
+	blockTab[blockTab[index].next].prev = blockTab[index].prev;
+	blockTab[blockTab[index].prev].next = blockTab[index].next;
+      }
+    blockTab[index].reset();
+    mapBlock(blockNumber, blockTab[index], reused);
+    //    System.err.println("reuse "+index+" --> "+blockNumber+" "+nBlocks);
+    blockTab[index] = null;
+  }
+
+  private void moveToFront(int index)
+  {
+    if (index == oldest)
+      {
+	oldest = blockTab[index].next;
+	blockTab[index].prev = newest;
+	blockTab[newest].next = index;
+	newest = index;
+      }
+    else if (index != newest)
+      {
+	blockTab[blockTab[index].next].prev = blockTab[index].prev;
+	blockTab[blockTab[index].prev].next = blockTab[index].next;
+	blockTab[index].prev = newest;
+	blockTab[newest].next = index;
+	newest = index;
+      }
+  }
+  
+  public void writeBlock(Block bl) throws IOException
+  {
+    file.seek(blockSize * bl.number);
+    bl.writeOut(file);
+  }
+
+  public void mapBlocks(BlockProcessor processor) throws IOException
+  {
+    long nBlocks = file.length()/blockSize;
+    Block block = bfactory.makeBlock();
+    file.seek(0);
+    for (int i = 0; i < nBlocks; i++)
+      processor.process(Block.readIn(file, block));
+  }
+
+  /**
+   * Debug code
+   */
+
+  private boolean debug=false;
+  private void debug(String msg) {
+    if (debug) {
+      System.err.println("Block Manager: "+msg);
+    }
+  }
+
+}
diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/BlockManagerParameters.java b/jhMaster/JSearch/client/com/sun/java/help/search/BlockManagerParameters.java
new file mode 100644
index 0000000000000000000000000000000000000000..44bdeed2e46eda88fbcae5a0a76bb0c1e1ca1244
--- /dev/null
+++ b/jhMaster/JSearch/client/com/sun/java/help/search/BlockManagerParameters.java
@@ -0,0 +1,112 @@
+/*
+ * @(#)BlockManagerParameters.java	1.11 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @(#) BlockManagerParameters.java 1.3 - last change made 03/17/98
+ */
+
+package com.sun.java.help.search;
+
+import java.net.URL;
+
+/**
+ * This class contains the parameters necessary for Dict BlockManager
+ *
+ * @date   2/3/98
+ * @author Jacek R. Ambroziak
+ * @author Roger D. Brinkley
+ */
+
+class BlockManagerParameters extends DBPartParameters
+{
+  private URL url;
+
+  private int blockSize;
+  protected int root;
+
+  public BlockManagerParameters(Schema schema, String partName)
+    throws Exception
+  {
+    super(schema, partName);
+    url = schema.getURL(partName);
+    debug(url.toString());
+  }
+  
+  public boolean readState()
+  {
+    if (parametersKnown())
+      {
+	blockSize = integerParameter("bs");
+	//	System.err.println("blockSize " + blockSize);
+	root = integerParameter("rt");
+	return true;
+      }
+    else
+      return false;
+  }
+
+  public void updateSchema(String params) {
+    super.updateSchema("bs="+blockSize+" rt="+root+" fl=-1 " + params);
+  }
+
+  public BlockManagerParameters(URL url, int blockSize, int root)
+  {
+    this.url = url;
+    this.blockSize = blockSize;
+    this.root = root;
+  }
+
+  public URL getURL() {
+    return url;
+  }
+
+  public int getBlockSize() {
+    return blockSize;
+  }
+
+  public void setBlockSize(int size) {
+    blockSize = size;
+  }
+
+  public int getRootPosition() {
+    return root;
+  }
+
+  public void setRoot(int root) {
+    this.root = root;
+  }
+  /**
+   * Debug code
+   */
+
+  private boolean debug=false;
+  private void debug(String msg) {
+    if (debug) {
+      System.err.println("Block Manager Parameters: "+msg);
+    }
+  }
+}
diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/BlockProcessor.java b/jhMaster/JSearch/client/com/sun/java/help/search/BlockProcessor.java
new file mode 100644
index 0000000000000000000000000000000000000000..0b1494f079fc48c73b9831b6d99825a08b295098
--- /dev/null
+++ b/jhMaster/JSearch/client/com/sun/java/help/search/BlockProcessor.java
@@ -0,0 +1,33 @@
+/*
+ * @(#)BlockProcessor.java	1.6 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.java.help.search;
+
+interface BlockProcessor
+{
+  public void process(Block block);
+}
diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/BtreeDict.java b/jhMaster/JSearch/client/com/sun/java/help/search/BtreeDict.java
new file mode 100644
index 0000000000000000000000000000000000000000..c84f8467aa76ac716dc33f585948e044b8e1fca3
--- /dev/null
+++ b/jhMaster/JSearch/client/com/sun/java/help/search/BtreeDict.java
@@ -0,0 +1,327 @@
+/*
+ * @(#)BtreeDict.java	1.14 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @(#) BtreeDict.java 1.5 - last change made 03/18/98
+ */
+
+package com.sun.java.help.search;
+
+import java.io.*;
+
+/**
+ * @version	1.5	03/18/98
+ * @author Jacek R. Ambroziak
+ * @author Roger D. Brinkley
+ */
+
+public class BtreeDict
+{
+  protected static final int ENTHEADERLEN = 6;
+  protected static final int BLOCKSIZE = 2048;
+  protected static final int DATALEN = BLOCKSIZE - Block.HEADERLEN;
+  protected static final int MaxKeyLength = 255;
+  //!!! Careful with that number, Eugene
+  protected static final int lastPtrIndex = 508;
+
+  protected class DictBlock extends Block
+  {
+    public DictBlock() {
+      super(BLOCKSIZE);
+    }
+  
+    public int free() {
+      return free + firstEntry();
+    }
+  
+    public int numberOfEntries() {
+      return integerAt(0);
+    }
+  
+    public int nthPointer(int n) {
+      return integerAt(4*(n + 1));
+    }
+  
+    public int getChildIdx(int index) {
+      return nthPointer(lastPtrIndex - index);
+    }
+  
+    public int entryKeyLength(int i) {
+      return data[i] & 0xFF;
+    }
+  
+    public int entryCompression(int i) {
+      return data[i + 1] & 0xFF;
+    }
+  
+    public int entryID(int i) {
+      return integerAt(i + 2);
+    }
+  
+    public int entryLength(int entry) {
+      return ENTHEADERLEN + entryKeyLength(entry);
+    }
+     
+    public int entryKey(int entry) {
+      return entry + ENTHEADERLEN;
+    }
+
+    public int firstEntry() {
+      return 4;
+    }
+
+    public int nextEntry(int entry) {
+      return entry + entryLength(entry);
+    }
+  
+    public void restoreKeyInBuffer(int entry, byte[] buffer)
+    {
+      int howMany = entryKeyLength(entry);
+      int where = entryCompression(entry);
+      int from = entryKey(entry);
+      while (howMany-- > 0)
+	buffer[where++] = data[from++];
+    }
+    
+    public String restoreKey(int entry, byte[] buffer)
+    {
+      int howMany = entryKeyLength(entry);
+      int where = entryCompression(entry);
+      int from = entryKey(entry);
+      while (howMany-- > 0)
+	buffer[where++] = data[from++];
+      String string = null;
+      try {
+	  string = new String(buffer, 0, where, "UTF8");
+      } catch (java.io.UnsupportedEncodingException e) {
+	  // ignore
+      }
+      return string;
+    }
+  
+    public String findID(int id) throws Exception
+    {
+      byte[] buffer = new byte[MaxKeyLength];
+      int freeSpace = free();
+      for (int ent = firstEntry(); ent < freeSpace; ent = nextEntry(ent))
+	if (entryID(ent) == id) // found
+	  return restoreKey(ent, buffer);
+	else
+	  restoreKeyInBuffer(ent, buffer);
+      throw new Exception("ID not found in block");
+    }
+  
+    protected void setBlockNumbers(final int[] blocks)
+    {
+      for (int e = firstEntry(); e < free; e = nextEntry(e))
+	blocks[entryID(e)] = number;
+    }
+  
+    /*
+    protected void doMap(BtreeDict owner, EntryProcessor processor)
+      throws Exception
+    {
+      byte[] buffer = new byte[MaxKeyLength];
+      final int freeSpace = free();
+      int entryPtr = firstEntry();
+      if (isLeaf)
+	while (entryPtr < freeSpace) {
+	  processor.processEntry(restoreKey(entryPtr, buffer),
+				 entryID(entryPtr));
+	  entryPtr = nextEntry(entryPtr);
+	}
+      else
+	{
+	  owner.lock(this);
+	  int entryIdx  = 0;
+	  while (entryPtr < freeSpace) {
+	    owner.accessBlock(getChildIdx(entryIdx)).doMap(owner,processor);
+	    processor.processEntry(restoreKey(entryPtr, buffer),
+				   entryID(entryPtr));
+	    entryPtr = nextEntry(entryPtr);
+	    ++entryIdx;
+	  }
+	  owner.accessBlock(getChildIdx(entryIdx)).doMap(owner, processor);
+	  owner.unlock(this);
+	}
+    }
+    */
+  }
+  // end of internal class
+
+  protected BlockManager blockManager;
+  protected int          root;
+  protected int[]        blocks;
+  
+  protected BtreeDict() {/*empty*/}
+
+  public BtreeDict(BtreeDictParameters params) throws Exception
+  {
+    init(params, false, new BlockFactory() {
+      public Block makeBlock() { return new DictBlock(); }
+    });
+    blocks = new int[params.getFreeID()];
+    setBlocks(blocks);
+  }
+
+  public int fetch(String key) throws Exception
+  {
+    //    System.err.println("fetching " + key);
+    byte[] bytes = key.getBytes("UTF8");
+    byte[] Key = new byte[bytes.length + 1];
+    System.arraycopy(bytes, 0, Key, 0, bytes.length);
+    Key[bytes.length] = 0;		// sentinel
+    return find(accessBlock(root), Key);
+  }
+  
+  public String fetch(int conceptID) throws Exception {
+    return findID(blocks[conceptID], conceptID);
+  }
+  
+  public void close() throws Exception {
+    blockManager.close();
+  }
+  
+  protected void init(BtreeDictParameters params, boolean update,
+		      BlockFactory bfactory) throws Exception
+  {
+    blockManager = new BlockManager(params, update, bfactory);
+    root = params.getRootPosition();
+  }
+  
+  protected void lock(Block bl) {
+    blockManager.lockBlock(bl.number);
+  }
+  
+  protected void unlock(Block bl) {
+    blockManager.unlockBlock(bl.number);
+  }
+  
+  protected DictBlock accessBlock(int index) throws Exception {
+    return (DictBlock)blockManager.accessBlock(index);
+  }
+  
+  protected DictBlock child(DictBlock bl, int index) throws Exception {
+    return accessBlock(bl.getChildIdx(index));
+  }
+  
+  private String findID(int blNum, int id) throws Exception {
+    return accessBlock(blNum).findID(id);
+  }
+
+  private int find(DictBlock bl, byte[] key, int index) throws Exception {
+    return bl.isLeaf ? 0 : find(child(bl, index), key);
+  }
+
+  private int find(DictBlock bl, byte[] key) throws Exception
+  {
+    int inputKeyLen = key.length - 1;
+    int entryPtr    = bl.firstEntry();
+    int freeSpace   = bl.free();
+    int nCharsEqual = 0;
+    int compression = 0;
+
+    for (int entryIdx = 0;;)
+      {
+	if (entryPtr == freeSpace)
+	  return find(bl, key, bl.numberOfEntries());
+	else if (compression == nCharsEqual)
+	  {
+	    int keyLen = bl.entryKeyLength(entryPtr);
+	    int keyPtr = bl.entryKey(entryPtr), i;
+	    for (i = 0;
+		 i < keyLen && key[nCharsEqual] == bl.data[keyPtr + i];
+		 i++)
+	      ++nCharsEqual;
+	    if (i == keyLen)
+	      {
+		if (nCharsEqual == inputKeyLen)
+		  return bl.entryID(entryPtr);
+	      }
+	    else if ((key[nCharsEqual]&0xFF) < (bl.data[keyPtr + i]&0xFF))
+	      return find(bl, key, entryIdx);
+	  }
+	else if (compression < nCharsEqual) // compression dropped
+	  return find(bl, key, entryPtr == freeSpace
+		      ? bl.numberOfEntries() : entryIdx);
+	do {
+	  entryPtr = bl.nextEntry(entryPtr);
+	  ++entryIdx;
+	}
+	while (bl.entryCompression(entryPtr) > nCharsEqual);
+	compression = bl.entryCompression(entryPtr);
+      }
+  }
+
+  private void setBlocks(final int[] blocks) throws Exception
+  {
+    long start = System.currentTimeMillis();
+    blockManager.mapBlocks(new BlockProcessor() {
+      public void process(Block block) {
+	((DictBlock)block).setBlockNumbers(blocks);
+      }
+    });
+    debug((System.currentTimeMillis() - start) + " msec; TMAP");
+  }
+
+  /*
+    can go to Full
+  public void map(EntryProcessor processor) throws Exception {
+    accessBlock(root).doMap(this, processor);
+  }
+  */
+  /**
+   * Debug code
+   */
+
+  private boolean debug=false;
+  private void debug(String msg) {
+    if (debug) {
+      System.err.println("BtreeDict: "+msg);
+    }
+  }
+
+  public static void main(String[] args)
+  {
+    try {
+      Schema schema = new Schema(null, args[0], false);
+      BtreeDictParameters params = new BtreeDictParameters(schema, "TMAP");
+      BtreeDict source = new BtreeDict(params);
+      /*
+      source.map(new EntryProcessor() {
+	public void processEntry(String key, int id) {
+	  System.out.println(key + " " + id);
+	}
+      });
+      */
+    }
+    catch (Exception e) {
+      System.err.println(e);
+      e.printStackTrace();
+    }
+  }
+}
diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/BtreeDictParameters.java b/jhMaster/JSearch/client/com/sun/java/help/search/BtreeDictParameters.java
new file mode 100644
index 0000000000000000000000000000000000000000..2a99f415a1629fcb3429eb91e9cc69a294ededb9
--- /dev/null
+++ b/jhMaster/JSearch/client/com/sun/java/help/search/BtreeDictParameters.java
@@ -0,0 +1,205 @@
+/*
+ * @(#)BtreeDictParameters.java	1.15 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @(#) BtreeDictParameters.java 1.5 - last change made 04/01/98
+ */
+
+package com.sun.java.help.search;
+
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.StringTokenizer;
+import java.io.*;
+
+/**
+ *
+ * @version	1.5	04/01/98
+ * @author Jacek R. Ambroziak
+ * @author Roger D. Brinkley
+ * @author Eduardo Pelegri-Llopart
+ */
+
+class BtreeDictParameters extends BlockManagerParameters
+{
+  private int id1;
+  private String dirName;
+  
+  // some form of this is needed for starting new DBs
+  public BtreeDictParameters(URL fileName, int blockSize, int root,
+			     int freeID)
+  {
+    super(fileName, blockSize, root);
+    id1 = freeID;
+  }
+    
+  public BtreeDictParameters(Schema schema, String partName)
+    throws Exception
+  {
+    super(schema, partName);
+  }
+  
+  public boolean readState()
+  {
+    if (super.readState())
+      {
+	setFreeID(integerParameter("id1"));
+	return true;
+      }
+    else
+      return false;
+  }
+
+  public void writeState() {
+  }
+  
+  public int getFreeID() {
+    return id1;
+  }
+
+  public final void setFreeID(int id) {
+    id1 = id;
+  }
+
+  private void setDirName(String dirName) {
+    this.dirName = dirName;
+  }
+
+  public static BtreeDictParameters create(URL dirName)
+  {
+    try {
+      URL url = new URL(dirName, "TMAP");
+      BtreeDictParameters bdp = null;
+      //	new BtreeDictParameters(url, 2048, 0, 1);
+      bdp.setDirName(dirName.getFile());
+      return bdp;
+    } catch (java.net.MalformedURLException e) {
+      System.out.println ("Couldn't create " + dirName + File.separator + "TMAP");
+    }
+    return null;
+  }
+
+  public static BtreeDictParameters read(String dir, URL hsBase)
+    throws Exception
+  {
+    URL baseURL=null, url, tmapURL=null;
+    URLConnection connect;
+    BufferedReader in;
+    File file;
+
+    int blockSize = -1;
+    int rootPosition = -1;
+    int freeID = -1;
+
+    if (hsBase == null) {
+	file = new File(dir);
+	if (file.exists()) {
+	    // On Win32 we need to convert all "\" to "/"
+	    if (File.separatorChar != '/') {
+		dir = dir.replace(File.separatorChar, '/');
+	    }
+	    // Make sure the last character is a file separator
+	    if (dir.lastIndexOf(File.separatorChar)
+		!= dir.length() - 1) {
+		dir = dir.concat(File.separator);
+	    }
+	    debug ("file:" + dir);
+	    // Use a file protocol
+	    baseURL = new URL("file", "", dir);
+	} else {
+	    // Assume that some protocol was specified and try it
+	baseURL = new URL(dir);
+      }
+    }
+      
+    // Read the SCHEMA data
+    if (hsBase != null) {
+      url = new URL(hsBase, dir + "/SCHEMA");
+    } else {
+      url = new URL(baseURL, "SCHEMA");
+    }
+    connect = url.openConnection();
+
+    in = new BufferedReader
+      (new InputStreamReader(connect.getInputStream()));
+
+    // This needs to be replaced with our XML Parser
+    String line;
+    do {
+      line = in.readLine();
+    }
+    while (!line.startsWith("TMAP"));
+    in.close();
+    StringTokenizer tokens = new StringTokenizer(line, " =");
+    tokens.nextToken();		// skip over 'TMAP'
+    while (tokens.hasMoreTokens())
+      {
+	String token = tokens.nextToken();
+	if (token.equals("bs"))
+	  blockSize = Integer.parseInt(tokens.nextToken());
+	else if (token.equals("rt"))
+	  rootPosition = Integer.parseInt(tokens.nextToken());
+	else if (token.equals("id1"))
+	  freeID = Integer.parseInt(tokens.nextToken());
+      }
+
+    if (hsBase != null) {
+      tmapURL = new URL(hsBase, dir + "/TMAP");
+    } else {
+      tmapURL = new URL(baseURL, "TMAP");
+    }
+    BtreeDictParameters bdp = null;
+    //      new BtreeDictParameters(tmapURL, blockSize, rootPosition, freeID);
+
+    if (hsBase == null) {
+      bdp.setDirName(Utilities.URLDecoder(baseURL.getFile()));
+    }
+    return bdp;
+  }
+
+  public void updateSchema() {
+    super.updateSchema("id1="+id1+" id2=1");
+  }
+    
+  public void write() throws java.io.IOException
+  {
+    FileWriter out = new FileWriter(dirName + "/SCHEMA");
+    out.write("JavaSearch 1.0\n");
+    out.write("TMAP bs=2048 rt="+root+" fl=-1 id1="+id1+" id2=1\n");
+    out.close();
+  }
+
+  /**
+   * For printf debugging.
+   */
+  private static boolean debugFlag = false;
+  private static void debug(String str) {
+    if( debugFlag ) {
+      System.out.println("BtreeDictParamters: " + str);
+    }
+  }
+}
diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/ByteArrayDecompressor.java b/jhMaster/JSearch/client/com/sun/java/help/search/ByteArrayDecompressor.java
new file mode 100644
index 0000000000000000000000000000000000000000..38c7f6c19d0cebca50459e0032ed39eccdbfee73
--- /dev/null
+++ b/jhMaster/JSearch/client/com/sun/java/help/search/ByteArrayDecompressor.java
@@ -0,0 +1,60 @@
+/*
+ * @(#)ByteArrayDecompressor.java	1.6 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @date   1/13/98
+ * @author Jacek R. Ambroziak
+ * @group  Sun Microsystems Laboratories
+ */
+
+package com.sun.java.help.search;
+
+class ByteArrayDecompressor extends Decompressor
+{
+  private byte[] _array;
+  private int    _index;
+  private int    _index0;
+  
+  public ByteArrayDecompressor(byte[] array, int index) {
+    initReading(array, index);
+  }
+
+  public void initReading(byte[] array, int index)
+  {
+    _array = array;
+    _index = _index0 = index;
+    initReading();
+  }
+
+  public int bytesRead() {
+    return _index - _index0;
+  }
+
+  protected int getNextByte() throws Exception {
+    return _array[_index++] & 0xFF;
+  }
+}
diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/Compressor.java b/jhMaster/JSearch/client/com/sun/java/help/search/Compressor.java
new file mode 100644
index 0000000000000000000000000000000000000000..c551c2e95c722740d2edc17e902b462dcd0a143f
--- /dev/null
+++ b/jhMaster/JSearch/client/com/sun/java/help/search/Compressor.java
@@ -0,0 +1,201 @@
+/*
+ * @(#)Compressor.java	1.9 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @date   2/17/98
+ * @author Jacek R. Ambroziak
+ * @group  Sun Microsystems Laboratories
+ */
+
+package com.sun.java.help.search;
+
+import java.io.*;
+
+class Compressor
+{
+  private static final int NBits  = 32;
+  private static final int BeginK =  5;
+
+  private BitBuffer _buffer = new BitBuffer();
+
+  public void write(DataOutput out) throws IOException {
+    _buffer.write(out);
+  }
+
+  public int byteCount() {
+    return _buffer.byteCount();
+  }
+
+  public void clear() {
+    _buffer.clear();
+  }
+
+  public void concatenate(Compressor other) {
+    _buffer.concatenate(other._buffer);
+  }
+
+  public void encode(IntegerArray pos, int k)
+  {
+    int power = 1 << k, n1 = 0;
+    for (int i = 0; i < pos.cardinality(); i++)
+      {
+	int n2 = pos.at(i) >>> k;
+	int rem = pos.at(i) % power;
+	if (n2 != n1)
+	  {
+	    int min = n1, a = n1;
+	    int lev = 0, power2 = 1;
+	    if (n2 > n1)
+	      for (int max = n1; max < n2; a >>>= 1, power2 <<= 1, lev++)
+		if ((a & 1) != 0)
+		  min -= power2;
+		else
+		  max += power2;
+	    else
+	      for ( ; min > n2; a >>>= 1, power2 <<= 1, lev++)
+		if ((a & 1) != 0)
+		  min -= power2;
+	    // lev 0s, 1, lev bits of (n2 - min) plus following value
+	    // no 'V' symbol needed here
+	    if (lev*2 + 1 + k <= NBits)
+	      _buffer.append((1<<lev | (n2 - min)) << k | rem, lev*2+1+k);
+	    else
+	      {
+		if (lev*2 + 1 <= NBits)
+		  _buffer.append(1 << lev | (n2 - min), lev*2 + 1);
+		else
+		  {
+		    _buffer.append(0, lev);
+		    _buffer.append(1 << lev | (n2 - min), lev + 1);
+		  }
+		_buffer.append(rem, k);
+	      }
+	    n1 = n2;
+	  }
+	else
+	  _buffer.append(rem | power, k + 1); // 'V' + value
+      }
+    _buffer.append(2 | n1 & 1, 3); // marking end
+    _buffer.close();
+  }
+
+  public void encode(IntegerArray pos, IntegerArray len, int k, int k2)
+  {
+    int power = 1 << k, n1 = 0;
+    for (int i = 0; i < pos.cardinality(); i++)
+      {
+	int n2 = pos.at(i) >>> k;
+	int rem = pos.at(i) % power;
+	if (n2 != n1)
+	  {
+	    int min = n1, a = n1;
+	    int lev = 0, power2 = 1;
+	    if (n2 > n1)
+	      for (int max = n1; max < n2; a >>>= 1, power2 <<= 1, lev++)
+		if ((a & 1) != 0)
+		  min -= power2;
+		else
+		  max += power2;
+	    else
+	      for ( ; min > n2; a >>>= 1, power2 <<= 1, lev++)
+		if ((a & 1) != 0)
+		  min -= power2;
+	    // lev 0s, 1, lev bits of (n2 - min) plus following value
+	    if (lev*2 + 1 + k <= NBits)
+	      _buffer.append((1<<lev | (n2 - min)) << k | rem, lev*2+1+k);
+	    else
+	      {
+		if (lev*2 + 1 <= NBits)
+		  _buffer.append(1 << lev | (n2 - min), lev*2 + 1);
+		else
+		  {
+		    _buffer.append(0, lev);
+		    _buffer.append(1 << lev | (n2 - min), lev + 1);
+		  }
+		_buffer.append(rem, k);
+	      }
+	    _buffer.append(len.at(i), k2);
+	    n1 = n2;
+	  }
+	else
+	  _buffer.append((rem|power)<<k2 | len.at(i), k+k2+1); // 'V' + v1,v2
+      }
+    _buffer.append(2 | n1 & 1, 3); // marking end
+    _buffer.close();
+  }
+  
+  // k: starting value for minimization  
+  public int minimize(IntegerArray array, int startK)
+  {
+    BitBuffer saved = new BitBuffer();
+    int minK = startK;
+    _buffer.clear();
+    encode(array, startK);
+    int min = _buffer.bitCount();	// init w/ first value
+    saved.setFrom(_buffer);
+  
+    _buffer.clear();
+    encode(array, startK + 1);
+
+    if (_buffer.bitCount() < min)
+      {
+	int k = startK + 1;
+	do {
+	  saved.setFrom(_buffer);
+	  min = _buffer.bitCount();
+	  minK = k;
+	  _buffer.clear();
+	  encode(array, ++k);
+	}
+	while (_buffer.bitCount() < min);
+      }
+    else				// try smaller values through 1
+      for (int k = startK - 1; k > 0; k--)
+	{
+	  _buffer.clear();
+	  encode(array, k);
+	  if (_buffer.bitCount() < min)
+	    {
+	      saved.setFrom(_buffer);
+	      min = _buffer.bitCount();
+	      minK = k;
+	    }
+	  else
+	    break;
+	}
+  
+    _buffer.setFrom(saved);
+    return minK;
+  }
+  
+  public int compressAscending(IntegerArray array)
+  {
+    IntegerArray differences = new IntegerArray(array.cardinality());
+    array.toDifferences(differences);
+    return minimize(differences, BeginK);
+  }
+}
diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/CompressorIterator.java b/jhMaster/JSearch/client/com/sun/java/help/search/CompressorIterator.java
new file mode 100644
index 0000000000000000000000000000000000000000..f40ee6badc9ac81dbbd6a178e866fb5e44e126fa
--- /dev/null
+++ b/jhMaster/JSearch/client/com/sun/java/help/search/CompressorIterator.java
@@ -0,0 +1,40 @@
+/*
+ * @(#)CompressorIterator.java	1.6 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @date   1/13/98
+ * @author Jacek R. Ambroziak
+ * @group  Sun Microsystems Laboratories
+ */
+
+package com.sun.java.help.search;
+
+interface CompressorIterator
+{
+  public void value(int value);
+}
+  
diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/ConceptData.java b/jhMaster/JSearch/client/com/sun/java/help/search/ConceptData.java
new file mode 100644
index 0000000000000000000000000000000000000000..d78023ed6c3f8f923386910ae19c90625963e18c
--- /dev/null
+++ b/jhMaster/JSearch/client/com/sun/java/help/search/ConceptData.java
@@ -0,0 +1,150 @@
+/*
+ * @(#)ConceptData.java	1.6 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @date   1/13/98
+ * @author Jacek R. Ambroziak
+ * @group  Sun Microsystems Laboratories
+ */
+
+package com.sun.java.help.search;
+
+class ConceptData
+{
+  private final byte    _query;
+  private final byte    _nColumns;
+  private final byte    _role;
+  private final int    _concept;
+  private int          _conceptLength;
+  private final int    _proximity;
+  private final double _penalty;
+  private ConceptData _next;
+  
+  private static final int ProxPerTerm = 100;
+  
+  public ConceptData(int id, int role, double score, int query, int nColumns)
+  {
+    _query = (byte)query;
+    _nColumns = (byte)nColumns;
+    _concept = id;
+    _proximity = nColumns * ProxPerTerm;
+    _role = (byte)role;
+    _penalty = score;
+    _next = null;
+  }
+  
+  public int getConcept() {
+    return _concept;
+  }
+  
+  public double getPenalty() {
+    return _penalty;
+  }
+  
+  public int getConceptLength() {
+    return _conceptLength;
+  }
+  
+  public byte getRole() {
+    return _role;
+  }
+
+  public byte getQuery() {
+    return _query;
+  }
+
+  public byte getNColumns() {
+    return _nColumns;
+  }
+
+  public double getScore() {
+    return _penalty;
+  }
+  
+  public ConceptData getNext() {
+    return _next;
+  }
+  
+  public int getQueryMask() {
+    return (_next != null ? _next.getQueryMask() : 0) | (1 << _query);
+  }
+
+  public void setConceptLength(int length)
+  {
+    _conceptLength = length;
+    if (_next != null)
+      _next.setConceptLength(length);
+  }
+  
+  public void setNext(ConceptData next) {
+    _next = next;
+  }
+  
+  boolean cEquals(ConceptData other) {
+    return _concept == other._concept;
+  }
+
+  boolean crEquals(ConceptData other) {
+    return _concept == other._concept && _role == other._role;
+  }
+  
+  boolean crqEquals(ConceptData other) {
+    return _concept == other._concept && _role == other._role &&
+      _query == other._query;
+  }
+  
+  void addLast(ConceptData other)
+  {
+    if (_next != null)
+      _next.addLast(other);
+    else
+      _next = other;
+  }
+
+  boolean compareWith(ConceptData other) {
+    return _concept < other._concept
+      || cEquals(other)  && _role < other._role
+      || crEquals(other) && _penalty < other._penalty;
+  }
+
+  public void runBy(Query[] queries)
+  {
+    ConceptData cd = this;
+    do
+      queries[cd._query].updateEstimate(cd._role, cd._penalty);
+    while ((cd = cd._next) != null);
+  }
+
+  public void generateFillers(RoleFiller[] array, int pos)
+  {
+    if (array[_query] != RoleFiller.STOP) // 'prohibited'
+      (new RoleFiller(_nColumns, this, _role, pos, pos + _proximity))
+	.use(array, _query);
+    if (_next != null)
+      _next.generateFillers(array, pos);
+  }
+}
diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/ConceptGroupGenerator.java b/jhMaster/JSearch/client/com/sun/java/help/search/ConceptGroupGenerator.java
new file mode 100644
index 0000000000000000000000000000000000000000..465be3692032c4f388a94793178f518e9d80b3ba
--- /dev/null
+++ b/jhMaster/JSearch/client/com/sun/java/help/search/ConceptGroupGenerator.java
@@ -0,0 +1,112 @@
+/*
+ * @(#)ConceptGroupGenerator.java	1.6 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @date   1/13/98
+ * @author Jacek R. Ambroziak
+ * @group  Sun Microsystems Laboratories
+ */
+
+package com.sun.java.help.search;
+
+import java.io.InputStream;
+
+class ConceptGroupGenerator implements CompressorIterator
+{
+  private static final int NConceptsInGroup =
+  DocumentCompressor.NConceptsInGroup;
+  private static final int BitsInLabel =
+  DocumentCompressor.BitsInLabel;
+  
+  private int           _last;
+  private ConceptData[] _table;
+  private Decompressor    _bits;
+  private int          _k1;
+  private final int     _k2 = BitsInLabel;
+  private ConceptData  _cData;
+
+  public ConceptGroupGenerator()
+  {
+    _k1 = 0;
+    _table = new ConceptData[NConceptsInGroup];
+    _last = 0;
+    _bits = null;
+  }
+    
+  public ConceptGroupGenerator(byte[] bytes, int index, int k)
+  {
+    _k1 = k;
+    _table = new ConceptData[NConceptsInGroup];
+    _last = 0;
+    _bits = new ByteArrayDecompressor(bytes, index);
+  }
+
+  public void init(byte[] bytes, int index, int k)
+  {
+    _k1 = k;
+    _bits = new ByteArrayDecompressor(bytes, index);
+    _last = 0;
+    for (int i = 0; i < NConceptsInGroup; i++)
+      _table[i] = null;
+  }
+
+  public void addTerms(int index, ConceptData terms) {
+    _table[index] = terms;
+  }
+
+  public int decodeConcepts(int k, int shift, int[] concepts) throws Exception {
+    return _bits.ascendingDecode(k, shift, concepts);
+  }
+
+  public int position() {
+    return _last;
+  }
+  
+  public void value(int value) {
+    _last += value;
+  }
+  
+  boolean next() throws Exception
+  {
+    try {
+      while (_bits.readNext(_k1, this))
+	if ((_cData = _table[_bits.read(_k2)]) != null)
+	  return true;
+      return false;
+    }
+    catch (Exception e) {
+      e.printStackTrace();
+      System.err.println(_bits);
+      System.err.println(_table);
+      throw e;
+    }
+  }
+  
+  public void generateFillers(RoleFiller[] array) {
+    _cData.generateFillers(array, _last);
+  }
+}
diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/ConceptList.java b/jhMaster/JSearch/client/com/sun/java/help/search/ConceptList.java
new file mode 100644
index 0000000000000000000000000000000000000000..4cc01d45ebfaa1833f8ee15520d264a71c2eb94d
--- /dev/null
+++ b/jhMaster/JSearch/client/com/sun/java/help/search/ConceptList.java
@@ -0,0 +1,61 @@
+/*
+ * @(#)ConceptList.java	1.6 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @date   1/13/98
+ * @author Jacek R. Ambroziak
+ * @group  Sun Microsystems Laboratories
+ */
+
+package com.sun.java.help.search;
+
+class ConceptList implements NonnegativeIntegerGenerator, CompressorIterator
+{
+  private ByteArrayDecompressor _list;
+  private byte _k;
+  private int  _value = 0;
+
+  public ConceptList(byte[] array, int index)
+  {
+    _k = array[index];
+    _list = new ByteArrayDecompressor(array, index + 1);
+  }
+  
+  // callback
+  public void value(int val) {
+    _value += val;
+  }
+  
+  public int first() throws Exception {
+    _value = 0;
+    return _list.readNext(_k, this) ? _value : END;
+  }
+
+  public int next() throws Exception {
+    return _list.readNext(_k, this) ? _value : END;
+  }
+}
diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/ConceptLocation.java b/jhMaster/JSearch/client/com/sun/java/help/search/ConceptLocation.java
new file mode 100644
index 0000000000000000000000000000000000000000..a171c12658173f127a5e5d25006aefbce4a05773
--- /dev/null
+++ b/jhMaster/JSearch/client/com/sun/java/help/search/ConceptLocation.java
@@ -0,0 +1,167 @@
+/*
+ * @(#)ConceptLocation.java	1.6 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @date   3/5/98
+ * @author Jacek R. Ambroziak
+ * @group  Sun Microsystems Laboratories
+ */
+
+package com.sun.java.help.search;
+
+class ConceptLocation
+{
+  private int _concept;
+  private int _begin;
+  private int _end;
+  
+  private abstract class ConceptLocationSorter
+  {
+    abstract public boolean smallerThan(ConceptLocation a, ConceptLocation b);
+    // part of quicksearch
+    private int partition(ConceptLocation[] array, int p, int r)
+    {
+      ConceptLocation x = array[p];
+      int i = p - 1, j = r + 1;
+      while (true)
+	{
+	  while (smallerThan(x, array[--j]))
+	    ;
+	  while (smallerThan(array[++i], x))
+	    ;
+	  if (i < j)
+	    {
+	      ConceptLocation t = array[i];
+	      array[i] = array[j];
+	      array[j] = t;
+	    }
+	  else
+	    return j;
+	}
+    }
+
+    public void quicksort(ConceptLocation[] array, int p, int r)
+    {
+      if (p < r)
+	{
+	  int q = partition(array, p, r);
+	  quicksort(array, p, q);
+	  quicksort(array, q + 1, r);
+	}
+    }
+  }
+
+  private class ConceptSorter extends ConceptLocationSorter
+  {
+    public boolean smallerThan(ConceptLocation a, ConceptLocation b) {
+      return a._concept < b._concept;
+    }
+  }
+  
+  private class PositionSorter extends ConceptLocationSorter
+  {
+    public boolean smallerThan(ConceptLocation a, ConceptLocation b) {
+      return a._begin < b._begin || a._begin == b._begin && a._end < b._end;
+    }
+  }
+  // sorter by concept ID
+  private static ConceptLocationSorter _cComp;
+  // sorter by position
+  private static ConceptLocationSorter _pComp;
+
+  private ConceptLocation()
+  {
+    _cComp = new ConceptSorter();
+    _pComp = new PositionSorter();
+  }
+
+  static { new ConceptLocation(); }
+
+  public ConceptLocation(int conceptID, int begin, int end)
+  {
+    _concept = conceptID;
+    _begin = begin;
+    _end = end;
+  }
+  
+  public boolean equals(ConceptLocation other) {
+    return _concept==other._concept&&_begin==other._begin&&_end==other._end;
+  }
+
+  public void setConcept(int concept) {
+    _concept = concept;
+  }
+  
+  public int getConcept() {
+    return _concept;
+  }
+  
+  public int getBegin() {
+    return _begin;
+  }
+  
+  public int getEnd() {
+    return _end;
+  }
+  
+  public int getLength() {
+    return _end - _begin;
+  }
+  
+  public static void sortByConcept(ConceptLocation[] array, int i1, int i2) {
+    _cComp.quicksort(array, i1, i2 - 1);
+  }
+  
+  public static void sortByPosition(ConceptLocation[] array, int i1, int i2) {
+    _pComp.quicksort(array, i1, i2 - 1);
+  }
+  
+  public void print() {
+    System.out.println(_concept+"\t"+_begin+"\t"+_end);
+  }
+
+  public static void main(String[] args)
+  {
+    int limit = 30, b;
+    ConceptLocation[] array = new ConceptLocation[limit];
+    for (int i = 0; i < limit; i++)
+      array[i] = new ConceptLocation((int)(Math.random()*1000),
+				     b = (int)(Math.random()*1000),
+				     b + (int)(Math.random()*10));
+    for (int i = 0; i < limit; i++)
+      array[i].print();
+    ConceptLocation.sortByConcept(array, 0, limit);
+    System.out.println("----------------------------------");
+    for (int i = 0; i < limit; i++)
+      array[i].print();
+    ConceptLocation.sortByPosition(array, 0, limit);
+    System.out.println("----------------------------------");
+    for (int i = 0; i < limit; i++)
+      array[i].print();
+  }
+}
+
diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/DBPartParameters.java b/jhMaster/JSearch/client/com/sun/java/help/search/DBPartParameters.java
new file mode 100644
index 0000000000000000000000000000000000000000..3da0b24796ed5aa6088b5e7e1ce7cf50e34f4632
--- /dev/null
+++ b/jhMaster/JSearch/client/com/sun/java/help/search/DBPartParameters.java
@@ -0,0 +1,68 @@
+/*
+ * @(#)DBPartParameters.java	1.6 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @version	1.5	03/18/98
+ * @author Jacek R. Ambroziak
+ */
+
+package com.sun.java.help.search;
+
+import java.util.Hashtable;
+import java.net.URL;
+
+public class DBPartParameters
+{
+  protected Schema _schema;
+  private String _partName;
+  private Hashtable _parameters;
+
+  protected DBPartParameters() {}
+
+  public DBPartParameters(Schema schema, String partName)
+  {
+    _schema = schema;
+    _partName = partName;
+    _parameters = schema.parameters(partName);
+  }
+  
+  protected boolean parametersKnown() {
+    return _parameters != null;
+  }
+  
+  protected void updateSchema(String parameters) {
+    _schema.update(_partName, parameters);
+  }
+  
+  public int integerParameter(String name) {
+    return Integer.parseInt(((String)_parameters.get(name)));
+  }
+
+  public URL getURL() throws Exception {
+    return _schema.getURL(_partName);
+  }
+}
diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/Decompressor.java b/jhMaster/JSearch/client/com/sun/java/help/search/Decompressor.java
new file mode 100644
index 0000000000000000000000000000000000000000..acf51c9d1532a17eb68a5057b67f7ae54bc0b7e5
--- /dev/null
+++ b/jhMaster/JSearch/client/com/sun/java/help/search/Decompressor.java
@@ -0,0 +1,185 @@
+/*
+ * @(#)Decompressor.java	1.7 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @date   1/13/98
+ * @author Jacek R. Ambroziak
+ * @group  Sun Microsystems Laboratories
+ */
+
+package com.sun.java.help.search;
+
+abstract class Decompressor
+{
+  private static final int BitsInByte = 8;
+  private static final int NBits = 32;
+  
+  private int _readByte;
+  private int _toRead = 0;
+  private int _path = 0;
+
+  abstract protected int getNextByte() throws Exception;
+
+  protected void initReading() {
+    _toRead = 0;
+  }
+    
+  private int countZeroes() throws Exception
+  {
+    for (int count = 0;; _readByte = getNextByte(), _toRead = BitsInByte)
+      while (_toRead-- > 0)
+	if ((_readByte & (1 << _toRead)) != 0)
+	  return count;
+	else
+	  ++count;
+  }
+  
+  // reads 1 bit; returns non-0 for bit "1"
+  private int read() throws Exception
+  {
+    if (_toRead-- > 0)
+      return _readByte & (1 << _toRead);
+    else
+      {  // get next word
+	_toRead = BitsInByte - 1;
+	return (_readByte = getNextByte()) & 0x80;
+      }
+  }
+  
+  public int read(int kBits) throws Exception
+  {
+    int shift = BitsInByte - _toRead;
+    if (kBits <= _toRead)
+      return ((_readByte<<shift) & 0xFF) >>> (shift + (_toRead-=kBits));
+    else
+      {
+	int result = _toRead > 0
+	  ? ((_readByte << shift) & 0xFF) >>> shift
+	  : 0;
+	for (kBits -= _toRead; kBits >= BitsInByte; kBits -= BitsInByte)
+	  result = (result << BitsInByte) | getNextByte();
+	if (kBits > 0)
+	  return (result << kBits)
+	    | ((_readByte = getNextByte()) >>> (_toRead = BitsInByte - kBits));
+	else
+	  {
+	    _toRead = 0;
+	    return result;
+	  }
+      }
+  }
+  
+  public void beginIteration() {
+    _path = 0;
+  }
+
+  public boolean readNext(int k, CompressorIterator it) throws Exception
+  {
+    if (read() != 0)
+      {
+	it.value(_path | read(k));
+	return true;
+      }
+    else
+      for (int count = 1;; _readByte = getNextByte(), _toRead = BitsInByte)
+	while (_toRead-- > 0)
+	  if ((_readByte & (1 << _toRead)) != 0)
+	    {
+	      int saved = _path;
+	      _path = ((_path >>> (k + count) << count) | read(count)) << k;
+	      if (_path != saved)
+		{
+		  it.value(_path | read(k));
+		  return true;
+		}
+	      else
+		return false;
+	    }
+	  else
+	    ++count;
+  }
+  
+  public void decode(int k, IntegerArray array) throws Exception
+  {
+    for (int path = 0;;)
+      if (read() != 0)
+	array.add(path | read(k));
+      else
+	{
+	  int count = countZeroes() + 1;
+	  int saved = path;
+	  path = ((path >>> (k + count) << count) | read(count)) << k;
+	  if (path != saved)	// convention for end
+	    array.add(path | read(k));
+	  else
+	    break;
+	}
+  }
+
+  public void ascDecode(int k, IntegerArray array) throws Exception
+  {
+    for (int path = 0, start = 0;;)
+      if (read() != 0)
+	array.add(start += path | read(k));
+      else
+	{
+	  int count = countZeroes() + 1;
+	  int saved = path;
+	  path = ((path >>> (k + count) << count) | read(count)) << k;
+	  if (path != saved)	// convention for end
+	    array.add(start += path | read(k));
+	  else
+	    break;
+	}
+  }
+  
+  public int ascendingDecode(int k, int start, int[] array) throws Exception
+  {
+    int path = 0, index = 0;
+  LOOP:
+    while (true)
+      if (read() != 0)
+	array[index++] = (start += path | read(k));
+      else
+	for (int cnt = 0;; _readByte = getNextByte(), _toRead = BitsInByte)
+	  while (_toRead-- > 0)
+	    if ((_readByte & (1 << _toRead)) != 0)
+	      {
+		++cnt;
+		int Path = ((path >>> (k + cnt) << cnt) | read(cnt)) << k;
+		if (Path != path)
+		  {
+		    array[index++] = (start += (path = Path) | read(k));
+		    continue LOOP;
+		  }
+		else
+		  return index;
+	      }
+	    else
+	      ++cnt;
+  }
+}
diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/DefaultSearchEngine.java b/jhMaster/JSearch/client/com/sun/java/help/search/DefaultSearchEngine.java
new file mode 100644
index 0000000000000000000000000000000000000000..af87dc844e131f7127fe69888f21fe2c9eaa7427
--- /dev/null
+++ b/jhMaster/JSearch/client/com/sun/java/help/search/DefaultSearchEngine.java
@@ -0,0 +1,108 @@
+/*
+ * @(#)DefaultSearchEngine.java	1.21 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @(#) DefaultSearchEngine.java 1.21 - last change made 10/30/06
+ */
+
+package com.sun.java.help.search;
+
+import java.io.*;
+import java.net.*;
+import java.text.*;
+import java.util.Vector;
+import java.util.Hashtable;
+import java.util.EventListener;
+import java.util.Locale;
+import javax.help.search.*;
+import com.sun.java.help.search.*;
+import java.security.InvalidParameterException;
+
+/**
+ * DefaultSearchEngine is the default search engine. 
+ *
+ * Search results are returned through SearchEvents to
+ * listeners that
+ * register with a SearchEngine instance through the Search Query.
+ *
+ * @author Roger D. Brinkley
+ * @author Eduardo Pelegri-Llopart
+ * @version	1.21	10/30/06
+ *
+ * @see javax.help.search.SearchEngine
+ * @see javax.help.search.SearchEvent
+ * @see javax.help.search.SearchListener
+ */
+public class DefaultSearchEngine extends SearchEngine {
+
+    private String urldata;	// just for debugging really
+    protected QueryEngine qe;
+
+    /**
+     * Create a DefaultSearchEngine 
+     */
+    public DefaultSearchEngine(URL base, Hashtable params) 
+	throws InvalidParameterException
+    {
+	super(base, params);
+
+	debug("Loading Search Database");
+	debug("  base: "+base);
+	debug("  params: "+params);
+
+	// Load the Query Engine and Search DB here
+	try {
+	    urldata = (String) params.get("data");
+	    qe = new QueryEngine(urldata, base);
+	} catch (Exception e) {
+	    if (debugFlag) {
+		System.err.println(" =========== ");
+		e.printStackTrace();
+	    }
+	    throw new InvalidParameterException();
+	}
+    }
+
+    public SearchQuery createQuery() {
+	return new DefaultSearchQuery(this);
+    }
+
+    protected QueryEngine getQueryEngine() {
+	return qe;
+    }
+
+    /**
+     * For printf debugging.
+     */
+    private static final boolean debugFlag = false;
+    private static void debug(String str) {
+        if( debugFlag ) {
+            System.out.println("DefaultSearchEngine: " + str);
+        }
+    }
+
+}
diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/DefaultSearchQuery.java b/jhMaster/JSearch/client/com/sun/java/help/search/DefaultSearchQuery.java
new file mode 100644
index 0000000000000000000000000000000000000000..e2357c4954aacd3a7387ae897a94eccb8858c8de
--- /dev/null
+++ b/jhMaster/JSearch/client/com/sun/java/help/search/DefaultSearchQuery.java
@@ -0,0 +1,141 @@
+/*
+ * @(#)DefaultSearchQuery.java	1.7 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @(#) DefaultSearchQuery.java 1.7 - last change made 10/30/06
+ */
+
+package com.sun.java.help.search;
+
+import java.io.*;
+import java.net.*;
+import java.text.*;
+import java.util.Vector;
+import java.util.Hashtable;
+import java.util.EventListener;
+import java.util.Locale;
+import javax.help.search.*;
+import com.sun.java.help.search.*;
+import java.security.InvalidParameterException;
+
+/**
+ * DefaultSearchQuery is the query using the default search engine. 
+ *
+ * Search results are returned through SearchEvents to
+ * listeners that register with this instance.
+ *
+ * @author Roger D. Brinkley
+ * @author Eduardo Pelegri-Llopart
+ * @version	1.7	10/30/06
+ *
+ * @see javax.help.search.SearchEngine
+ * @see javax.help.search.SearchQuery
+ * @see javax.help.search.SearchEvent
+ * @see javax.help.search.SearchListener
+ */
+public class DefaultSearchQuery extends SearchQuery implements Runnable {
+
+    private Thread thread = null;
+    private DefaultSearchEngine dhs;
+
+    /**
+     * Create a DefaultSearchEngine 
+     */
+    public DefaultSearchQuery(SearchEngine hs) {
+	super(hs);
+	if (hs instanceof DefaultSearchEngine) {
+	    dhs = (DefaultSearchEngine) hs;
+	}
+    }
+
+
+    /**
+     * Starts the search. The implementation is up to subclasses of SearchEngine.
+     * This method will invoke searchStarted on SearchListeners.
+     * @exception IllegalArgumentException The parameters are not 
+     * understood by this engine
+     * @exception IllegalStateException There is an active search in progress in this instance
+     */
+    public void start(String searchparams, Locale l) 
+	 throws IllegalArgumentException, IllegalStateException 
+    {
+	debug ("Starting Search");
+	if (isActive()) {
+	    throw new IllegalStateException();
+	}
+
+	// initialization
+	super.start(searchparams, l);
+
+	// Actually do the search
+	thread = new Thread(this, "QueryThread");
+	thread.start();
+    }
+
+    /**
+     * Stops the search. The implementation is up to the subcalsses of 
+     * SearchEngine. This method will invoke searchStopped on 
+     * SearchListeners.
+     */
+    public void stop() throws IllegalArgumentException, IllegalStateException {
+	debug ("Stop Search");
+	// Can no longer do a stop
+	// Let it continue to operate until it's completed
+	// on it's own. This is due to to the enherent problem 
+	// with thread.stop
+    }
+
+    public boolean isActive() {
+	if (thread == null) { 
+	    return false;
+	}
+	return thread.isAlive();
+    }
+
+    public void run() throws IllegalArgumentException{
+	QueryEngine qe = dhs.getQueryEngine();
+	try {
+	    qe.processQuery(searchparams, l, this);
+	} catch (Exception e) {
+	    e.printStackTrace();
+	    throw new IllegalArgumentException();
+	}
+	fireSearchFinished();
+	thread = null;
+    }
+
+    /**
+     * For printf debugging.
+     */
+    private static final boolean debugFlag = false;
+    private static void debug(String str) {
+        if( debugFlag ) {
+            System.out.println("DefaultSearchQuery: " + str);
+        }
+    }
+
+}
diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/DocumentCompressor.java b/jhMaster/JSearch/client/com/sun/java/help/search/DocumentCompressor.java
new file mode 100644
index 0000000000000000000000000000000000000000..e6fa13becf0b4590590e35dd24d8b48c4ffb73de
--- /dev/null
+++ b/jhMaster/JSearch/client/com/sun/java/help/search/DocumentCompressor.java
@@ -0,0 +1,385 @@
+/*
+ * @(#)DocumentCompressor.java	1.16 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @date   1/13/98
+ * @author Jacek R. Ambroziak
+ * @group  Sun Microsystems Laboratories
+ */
+
+package com.sun.java.help.search;
+
+import java.io.*;
+import java.net.URL;
+import java.net.URLConnection;
+
+class DocumentCompressor
+{
+  static public final int NConceptsInGroup = 16;
+  static public final int BitsInLabel = 4;
+  static public final int DefaultSize = 32;
+  
+  private int _nGroups;
+  private int _nExtents;
+  private int _freeComp;
+  private int _sizeComp = DefaultSize;
+  private int _kk;
+  private Compressor  _currentCompressor = null;
+  private Compressor[] _compressors = new Compressor[DefaultSize];
+  private Compressor   _kCompr = new Compressor();
+  private Compressor   _lCompr = new Compressor();
+  private Compressor   _mCompr = new Compressor();
+  private Compressor   _posCompressor = new Compressor();
+  private IntegerArray _kTable = new IntegerArray();// k's for the series
+  private IntegerArray _lTable = new IntegerArray();// lengths of the C/P groups
+  private IntegerArray _maxConcepts = new IntegerArray();// maximal concepts in CP
+  private IntegerArray _concepts = new IntegerArray();
+  private IntegerArray _documents = new IntegerArray();
+  private IntegerArray _offsets = new IntegerArray();
+  private IntegerArray _titles = new IntegerArray();
+  
+  private IntegerArray _positions = new IntegerArray();
+  private IntegerArray _labels = new IntegerArray();
+  private RandomAccessFile _posFile;
+
+  public DocumentCompressor(URL url) throws Exception
+  {
+    URL posURL = new URL(url, "POSITIONS");
+    if (isFileURL(posURL))
+      {
+	// this code should not be repeated
+	try {
+	  URL offURL = new URL(url, "OFFSETS");
+	  URLConnection connect = offURL.openConnection();
+	  BufferedInputStream in =
+	    new BufferedInputStream(connect.getInputStream());
+	
+	  int k1 = in.read();
+	  StreamDecompressor sddocs = new StreamDecompressor(in);
+	  sddocs.ascDecode(k1, _documents);
+	  int k2 = in.read();
+	  StreamDecompressor sdoffsets = new StreamDecompressor(in);
+	  sdoffsets.ascDecode(k2, _offsets);
+	  // decompress titles' ids table
+	  int k3 = in.read();
+	  StreamDecompressor sdtitles = new StreamDecompressor(in);
+	  sdtitles.decode(k3, _titles);
+	  in.close();
+	}
+	catch (java.io.FileNotFoundException e) {;}
+	_posFile = 
+	    new RandomAccessFile(Utilities.URLDecoder(posURL.getFile()), 
+				 "rw");
+      }
+    else
+      throw new IOException();
+  }
+    
+  private boolean isFileURL(URL url) {
+    return url.getProtocol().equalsIgnoreCase("file");
+  }
+
+  public void close(String indexFile) throws java.io.IOException
+  {
+    _posFile.close();
+    writeOutOffsets(indexFile);
+  }
+
+  public void compress(int docID, int titleID,
+		       ConceptLocation[] locations, int count,
+		       ConceptLocation[] extents, int extCount)
+    throws java.io.IOException
+  {
+    long start = System.currentTimeMillis();
+    encode(locations, count, NConceptsInGroup);
+    if (extCount > 0)
+      encodeExtents(extents, extCount);
+    finalizeEncoding();
+    debug((System.currentTimeMillis() - start) + " msec proc");
+  
+    int nBytes = byteCount();
+    
+    start = System.currentTimeMillis();
+    long currentEnd = _posFile.length();
+    _documents.add(docID);
+    _offsets.add((int)currentEnd);
+    _titles.add(titleID);
+    _posFile.seek(currentEnd);
+    writeOut(_posFile);
+    debug((System.currentTimeMillis() - start) + " msec file");
+    debug("nGroups = " + _nGroups);
+  }
+
+  private void writeOutOffsets(String indexFile) throws java.io.IOException
+  {
+    Compressor documents = new Compressor();
+    int k1 = documents.compressAscending(_documents);
+    Compressor offsets = new Compressor();
+    int k2 = offsets.compressAscending(_offsets);
+    Compressor titles = new Compressor();
+    int k3 = titles.minimize(_titles, 8); // the starting k
+    int nBytes = documents.byteCount();
+    RandomAccessFile out = new RandomAccessFile(indexFile, "rw");
+    out.seek(0);	// position at beginning
+    out.write(k1);
+    documents.write(out);
+    out.write(k2);
+    offsets.write(out);
+    out.write(k3);
+    titles.write(out);
+    out.close();
+  }
+  
+  private void encode(ConceptLocation[] locations, int count, int nConcepts)
+  {
+    final int initK = 4;
+    // first sort by concept only
+    ConceptLocation.sortByConcept(locations, 0, count);
+    // using the fact that concepts are already sorted
+    // count of groups of 'nConcepts'
+    // go for differences directly
+    clear();
+    int conceptCounter = 0;
+    int fromIndex = 0;
+    int prevMax = 0;
+    int last = locations[0].getConcept(); // init w/ first ID
+    nextCompressor();
+    _concepts.add(last);
+    for (int i = 0;;)
+      {
+	for (; i < count && locations[i].getConcept() == last; i++)
+	  locations[i].setConcept(conceptCounter);
+	if (i == count)
+	  {
+	    if (_concepts.cardinality() > 0)
+	      {
+		++_nGroups;
+		_kTable.add(_currentCompressor.minimize(_concepts, initK));
+	      }
+	    encodePositions(locations, fromIndex, i, BitsInLabel);
+	    break;
+	  }
+	else				// new concept (group?)
+	  {
+	    if (++conceptCounter == nConcepts)
+	      {
+		++_nGroups;
+		// we are looking at the beginning of a new group
+		// last is maximal for the group just finished
+		// it won't be stored in concepts array but maxConcepts
+		_concepts.popLast();
+		_maxConcepts.add(last - prevMax);
+		prevMax = last;
+		_kTable.add(_currentCompressor.minimize(_concepts, initK));
+		encodePositions(locations, fromIndex, i, BitsInLabel);
+		fromIndex = i;
+		nextCompressor();
+		_concepts.clear();
+		conceptCounter = 0;
+	      }
+	    _concepts.add(locations[i].getConcept() - last);
+	    last = locations[i].getConcept();
+	  }
+      }
+  }
+  
+  private void encodePositions(ConceptLocation[] locations, int from, int to,
+			       int cK)
+  {
+    final int initK = 3;
+    int lastPos, k;
+    // sort in place by positions only
+    ConceptLocation.sortByPosition(locations, from, to);
+    _positions.clear();
+    _labels.clear();
+    _positions.add(lastPos = locations[from].getBegin());
+    _labels.add(locations[from].getConcept()); // now: a label
+    // skip duplicates
+    for (int i = from, j = from + 1; j < to; j++)
+      if (locations[i].equals(locations[j]) == false)
+	{
+	  i = j;
+	  _positions.add(locations[i].getBegin() - lastPos);
+	  lastPos = locations[i].getBegin();
+	  _labels.add(locations[i].getConcept()); // now: a label
+	}
+    // first find k by minimizing just positions w/o labels
+    _kTable.add(k = _posCompressor.minimize(_positions, initK));
+    _posCompressor.clear();
+    _posCompressor.encode(_positions, _labels, k, cK);
+    _currentCompressor.concatenate(_posCompressor);
+  }
+  
+  private void encodeExtents(ConceptLocation[] extents, int extCount)
+  {
+    // side effects:
+    // 'k3' added to _kTable
+    // a number of compressors populated: header + lengths' lists
+    final int initK = 4;
+    int c = 0;
+    IntegerArray concepts = new IntegerArray(extCount); // differences
+    IntegerArray lengths = new IntegerArray();
+    IntegerArray kTable = new IntegerArray();
+    IntegerArray lTable = new IntegerArray();
+    // reserve a compressor for concatenated tables
+    nextCompressor();
+    Compressor extentsHeader = _currentCompressor;
+    for (int i = 0; i < extCount; i++)
+      if (extents[i].getConcept() != c)
+	{
+	  if (c != 0)
+	    {
+	      _nExtents++;
+	      nextCompressor();
+	      kTable.add(_currentCompressor.minimize(lengths, initK));
+	      lTable.add(_currentCompressor.byteCount());
+	    }
+	  concepts.add(extents[i].getConcept() - c);
+	  c = extents[i].getConcept();
+	  lengths.clear();
+	  lengths.add(extents[i].getLength());
+	}
+      else
+	lengths.add(extents[i].getLength());
+    // last table of lengths
+    nextCompressor();
+    kTable.add(_currentCompressor.minimize(lengths, initK));
+    lTable.add(_currentCompressor.byteCount());
+    Compressor compressor1 = new Compressor();
+    kTable.add(compressor1.minimize(lTable, initK));
+    Compressor compressor2 = new Compressor();
+    kTable.add(compressor2.minimize(concepts, initK));
+    _kTable.add(extentsHeader.minimize(kTable, initK)); // k3
+    extentsHeader.concatenate(compressor1);
+    extentsHeader.concatenate(compressor2);
+  }
+  
+  private void finalizeEncoding()
+  {
+    if (_nGroups > 1)
+      {
+	// if extents follow C/P groups we need the length of the last group
+	int limit = _nExtents > 0 ? _freeComp : _freeComp - 1;
+	for (int j = 0; j < limit; j++) // length of last not saved
+	  _lTable.add(_compressors[j].byteCount());
+	
+	_kTable.add(_mCompr.minimize(_maxConcepts, 3));
+	_kTable.add(_lCompr.minimize(_lTable, 3));
+	_kk = _kCompr.minimize(_kTable, 3);
+	_kCompr.concatenate(_lCompr);
+	_kCompr.concatenate(_mCompr);
+      }
+    else if (_nGroups == 1 && _nExtents > 0)
+      {
+	// length of the single C/P group packed with k-s
+	_kTable.add(_compressors[0].byteCount());
+	_kk = _kCompr.minimize(_kTable, 3);
+      }
+    debug("compr: "+byteCount()+" bytes");
+  }
+
+  private void writeOut(DataOutput out) throws java.io.IOException
+  {
+    if (_nExtents == 0)
+      if (_nGroups > 1)
+	{
+	  out.write(0x80 | _kk);
+	  _kCompr.write(out); // concatenated k,l,m
+	  for (int j = 0; j < _freeComp; j++)
+	    _compressors[j].write(out);
+	}
+      else			// single group, no extents; code: 00
+	{
+	  out.write(_kTable.at(0)); // k1
+	  out.write(_kTable.at(1)); // k2
+	  _compressors[0].write(out);	// C/P
+	}
+    else				// extents
+      {
+	out.write((_nGroups > 1 ? 0xC0 : 0x40) | _kk);
+	_kCompr.write(out);
+	for (int j = 0; j < _freeComp; j++)
+	  _compressors[j].write(out);
+      }
+  }
+  
+  private Compressor nextCompressor()
+  {
+    if (_freeComp == _sizeComp)
+      {
+	Compressor[] newArray = new Compressor[_sizeComp *= 2];
+	System.arraycopy(_compressors, 0, newArray, 0, _freeComp);
+	_compressors = newArray;
+      }
+    if (_compressors[_freeComp] == null)
+      _compressors[_freeComp] = new Compressor();
+    return _currentCompressor = _compressors[_freeComp++];
+  }
+
+  private int byteCount()
+  {
+    if (_nGroups == 1 && _nExtents == 0)
+      return 2 + _compressors[0].byteCount();
+    else
+      {
+	int result = 1;		// initial kk
+	result += _kCompr.byteCount();
+	for (int j = 0; j < _freeComp; j++)
+	  result += _compressors[j].byteCount();
+	return result;
+      }
+  }
+  
+  private void clear()
+  {
+    _nGroups = 0;
+    _nExtents = 0;
+    _kTable.clear();
+    _lTable.clear();
+    _concepts.clear();
+    _maxConcepts.clear();
+    _kCompr.clear();
+    _lCompr.clear();
+    _mCompr.clear();
+    for (int i = 0; i < _sizeComp; i++)
+      if (_compressors[i] != null)
+	_compressors[i].clear();
+    _freeComp = 0;
+    _currentCompressor = null;
+  }
+    /**
+     * Debug code
+     */
+
+    private static boolean debug=false;
+    private static void debug(String msg) {
+        if (debug) {
+            System.err.println("DocumentCompressor: "+msg);
+        }
+    }
+
+}
diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/Entry.java b/jhMaster/JSearch/client/com/sun/java/help/search/Entry.java
new file mode 100644
index 0000000000000000000000000000000000000000..9c54ed61a16a78f8759a2906e9c6200d5357e6a4
--- /dev/null
+++ b/jhMaster/JSearch/client/com/sun/java/help/search/Entry.java
@@ -0,0 +1,59 @@
+/*
+ * @(#)Entry.java	1.7 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.java.help.search;
+
+class Entry
+{
+  public byte[] key;
+  public int    id;
+  public int    block = -1;
+  
+  public Entry(byte[] key, int length, int id)
+  {
+    this.key = new byte[length + 1];
+    System.arraycopy(key, 0, this.key, 0, length);
+    this.key[length] = 0;
+    this.id = id;
+  }
+  
+  public byte[] getKey() {
+    return key;
+  }
+
+  public int getID() {
+    return id;
+  }
+
+  public boolean smallerThan(Entry other)
+  {
+    for (int i = 0; i < Math.min(key.length, other.key.length); i++)
+      if (key[i] != other.key[i])
+	return (key[i]&0xFF) - (other.key[i]&0xFF) < 0;
+    return false;
+  }
+}
diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/EntryProcessor.java b/jhMaster/JSearch/client/com/sun/java/help/search/EntryProcessor.java
new file mode 100644
index 0000000000000000000000000000000000000000..17d0c881853541e070801247edba76fd4af47c40
--- /dev/null
+++ b/jhMaster/JSearch/client/com/sun/java/help/search/EntryProcessor.java
@@ -0,0 +1,33 @@
+/*
+ * @(#)EntryProcessor.java	1.7 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.java.help.search;
+
+interface EntryProcessor
+{
+  public void processEntry(String string, int id);
+}
diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/GeneratorHeap.java b/jhMaster/JSearch/client/com/sun/java/help/search/GeneratorHeap.java
new file mode 100644
index 0000000000000000000000000000000000000000..621a6d750a68ce5279039e7cdae0625e3da20bd6
--- /dev/null
+++ b/jhMaster/JSearch/client/com/sun/java/help/search/GeneratorHeap.java
@@ -0,0 +1,119 @@
+/*
+ * @(#)GeneratorHeap.java	1.6 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @date   1/13/98
+ * @author Jacek R. Ambroziak
+ * @group  Sun Microsystems Laboratories
+ */
+
+package com.sun.java.help.search;
+
+class GeneratorHeap
+{
+  private static final int        InitSize = 128;
+  private int                     _heapSize = 0;
+  private ConceptGroupGenerator[] _heap;
+  private int                     _size = InitSize;
+  private int                     _free = 0;
+  
+  public GeneratorHeap() {
+    _heap = new ConceptGroupGenerator[InitSize];
+  }
+  
+  public void reset() {
+    _free = 0;
+  }
+  
+  public void addGenerator(ConceptGroupGenerator gen)
+  {
+    if (_free == _size)
+      {
+	ConceptGroupGenerator[] newArray =
+	  new ConceptGroupGenerator[_size *= 2];
+	System.arraycopy(_heap, 0, newArray, 0, _free);
+	_heap = newArray;
+      }
+    _heap[_free++] = gen;
+  }
+
+  private void buildHeap()
+  {
+    for (int i = _heapSize/2; i >= 0; i--)
+      heapify(i);
+  }
+
+  private void heapify(int i)
+  {
+    int r = (i + 1) << 1, l = r - 1;
+    int smallest = l<_heapSize&&_heap[l].position()<_heap[i].position()?l:i;
+  
+    if (r < _heapSize && _heap[r].position() < _heap[smallest].position())
+      smallest = r;
+    if (smallest != i)
+      {
+	ConceptGroupGenerator temp = _heap[smallest];
+	_heap[smallest] = _heap[i];
+	_heap[i] = temp;
+	heapify(smallest);
+      }
+  }
+
+  public boolean start(RoleFiller[] array) throws Exception
+  {
+    if ((_heapSize = _free) > 0)
+      {
+	for (int i = 0; i < _free; i++)
+	  _heap[i].next();
+	buildHeap();
+	_heap[0].generateFillers(array);
+	return true;
+      }
+    else
+      return false;
+  }
+
+  public boolean next(RoleFiller[] array) throws Exception
+  {
+    if (_heapSize > 0)
+      {
+	if (!_heap[0].next()) // no more
+	  if (_heapSize > 1)
+	    _heap[0] = _heap[--_heapSize];
+	  else
+	    {
+	      _heapSize = 0;
+	      return false;
+	    }
+	heapify(0);
+	_heap[0].generateFillers(array);
+	return true;
+      }
+    else
+      return false;
+  }
+}
diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/HitStore.java b/jhMaster/JSearch/client/com/sun/java/help/search/HitStore.java
new file mode 100644
index 0000000000000000000000000000000000000000..d3188c98fac961d967f0092c04860a021f3c1cda
--- /dev/null
+++ b/jhMaster/JSearch/client/com/sun/java/help/search/HitStore.java
@@ -0,0 +1,274 @@
+/*
+ * @(#)HitStore.java	1.7 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @date   1/13/98
+ * @author Jacek R. Ambroziak
+ * @group  Sun Microsystems Laboratories
+ */
+
+package com.sun.java.help.search;
+
+import java.util.Vector;
+
+class HitStoreNode
+{
+  private int           _free = 0;
+  private int           _size;
+  private QueryHit[]    _array;
+  private int           _hitCount = 0;
+  private double         _divider = 0.0;
+  private double         _min = 10000000.0;
+  private double         _max = 0.0;
+  private HitStoreNode[] _children = new HitStoreNode[2]; // left & right
+  private int           _index = 0;
+
+  public HitStoreNode(int size) {
+    _array = new QueryHit[_size = size];
+  }
+  
+  public QueryHit getNextHit() {
+    return _index < _free ? _array[_index++] : null;
+  }
+  
+  private void fastAdd(QueryHit hit)
+  {
+    _hitCount++;
+    _divider += hit.getScore();
+    if (hit.getScore() > _max)
+      _max = hit.getScore();
+    if (hit.getScore() < _min)
+      _min = hit.getScore();
+    _array[_free++] = hit;
+  }
+
+  public boolean add(QueryHit hit)
+  {
+    if (_array != null)
+      {
+	if (_free < _size)
+	  {
+	    fastAdd(hit);
+	    return false;
+	  }
+	else if (_min != _max)
+	  {
+	    split();
+	    _hitCount++;
+	    _children[hit.getScore() > _divider ? 1 : 0].fastAdd(hit);
+	    return true;
+	  }
+	else
+	  {
+	    QueryHit[] newArray = new QueryHit[_size *= 2];
+	    System.arraycopy(_array, 0, newArray, 0, _free);
+	    _array = newArray;
+	    fastAdd(hit);
+	    return true;
+	  }
+      }
+    else
+      {
+	_hitCount++;
+	return _children[hit.getScore() > _divider ? 1 : 0].add(hit);
+      }
+  }
+
+  private void split()
+  {
+    _children[0] = new HitStoreNode(_size);
+    _children[1] = new HitStoreNode(_size);
+    _divider /= _hitCount;	// becomes average
+    for (int i = 0; i < _free; i++)
+      _children[_array[i].getScore() > _divider ? 1 : 0].fastAdd(_array[i]);
+    _array = null;			// becomes internal
+  }
+  public int getCount() {
+    return _hitCount;
+  }
+  public double getDivider() {
+    return _divider;
+  }
+  public HitStoreNode getLChild() {
+    return _children[0];
+  }
+  public HitStoreNode getRChild() {
+    return _children[1];
+  }
+  public void setLChild(HitStoreNode node) {
+    _children[0] = node;
+  }
+  public void setRChild(HitStoreNode node) {
+    _children[1] = node;
+  }
+  public void decrementCount(int delta) {
+    _hitCount -= delta;
+  }
+  public boolean isLeaf() {
+    return _array != null;
+  }
+  
+  public void sort() {
+    quicksort(0, _free - 1);
+  }
+
+  public void gatherLeaves(Vector vector)
+  {
+    if (isLeaf())
+      vector.addElement(this);
+    else
+      {
+	getLChild().gatherLeaves(vector);
+	getRChild().gatherLeaves(vector);
+      }
+  }
+  
+  // part of quicksearch
+  private int partition(int p, int r)
+  {
+    QueryHit x = _array[p];
+    int i = p - 1, j = r + 1;
+    while (true)
+      {
+	while (x.betterThan(_array[--j]))
+	  ;
+	while (_array[++i].betterThan(x))
+	  ;
+	if (i < j)
+	  {
+	    QueryHit t = _array[i];
+	    _array[i] = _array[j];
+	    _array[j] = t;
+	  }
+	else
+	  return j;
+      }
+  }
+
+  private void quicksort(int p, int r)
+  {
+    if (p < r)
+      {
+	int q = partition(p, r);
+	quicksort(p, q);
+	quicksort(q + 1, r);
+      }
+  }
+}
+
+
+class HitStore
+{
+  private static final int ArraySize = 128;
+  private static final int DefaultLimit = 300;
+  
+  private HitStoreNode _root = new HitStoreNode(ArraySize);
+  private int           _limit;
+  private double        _standard;
+  private Vector       _leaves = null;
+  private HitStoreNode _current = null;
+
+  public HitStore(double initialStandard) {
+    this(initialStandard, DefaultLimit);
+  }
+  
+  public HitStore(double initialStandard, int limit)
+  {
+    _limit = limit;
+    _standard = initialStandard;
+  }
+  
+  public void addQueryHit(QueryHit hit) {
+    if(_root.add(hit))
+      adapt();
+  }
+  
+  private HitStoreNode getNextNode()
+  {
+    if (_leaves.size() > 0)
+      {
+	HitStoreNode node = (HitStoreNode)_leaves.firstElement();
+	_leaves.removeElementAt(0);
+	node.sort();
+	return node;
+      }
+    else
+      return null;
+  }
+
+  public QueryHit firstBestQueryHit()
+  {
+    _leaves = new Vector();
+    _root.gatherLeaves(_leaves);
+    _current = getNextNode();
+    return _current.getNextHit();
+  }
+  
+  public QueryHit nextBestQueryHit()
+  {
+    QueryHit result = _current.getNextHit();
+    if (result != null)
+      return result;
+    else if ((_current = getNextNode()) != null)
+      return _current.getNextHit();
+    else
+      return null;
+  }
+  
+  double getCurrentStandard() {
+    return _standard;
+  }
+  
+  private void adapt()
+  {
+    if (_root.getCount() > _limit)
+      if (!_root.isLeaf())
+	{
+	  HitStoreNode ptr = _root;
+	  // find rightmost internal
+	  while (!ptr.getRChild().isLeaf())
+	    ptr = ptr.getRChild();
+      
+	  _standard = ptr.getDivider();
+      
+	  if (ptr == _root)
+	    _root = ptr.getLChild();
+	  else
+	    {
+	      int count = ptr.getRChild().getCount();
+	      HitStoreNode ptr2 = _root;
+	      while (ptr2.getRChild() != ptr)
+		{
+		  ptr2.decrementCount(count);
+		  ptr2 = ptr2.getRChild();
+		}
+	      ptr2.setRChild(ptr.getLChild());
+	    }
+	  ptr.setLChild(null);
+	}
+  }
+}
diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/IntegerArray.java b/jhMaster/JSearch/client/com/sun/java/help/search/IntegerArray.java
new file mode 100644
index 0000000000000000000000000000000000000000..dc4929c40bb039c3d84823685621f1d8b505a575
--- /dev/null
+++ b/jhMaster/JSearch/client/com/sun/java/help/search/IntegerArray.java
@@ -0,0 +1,115 @@
+/*
+ * @(#)IntegerArray.java	1.7 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @date   1/13/98
+ * @author Jacek R. Ambroziak
+ * @group  Sun Microsystems Laboratories
+ */
+
+package com.sun.java.help.search;
+
+class IntegerArray
+{
+  private int[] _array;
+  private int _size;
+  private int _free = 0;
+  private static final int InitialSize = 128;
+  
+  public IntegerArray() {
+    _array = new int[_size = InitialSize];
+  }
+  
+  public IntegerArray(int size) {
+    _array = new int[_size = size];
+  }
+
+  public void clear() {
+    _free = 0;
+  }
+
+  public int at(int index) {
+    return _array[index];
+  }
+
+  public void add(int value)
+  {
+    if (_free == _size)
+      growArray(_size * 2);
+    _array[_free++] = value;
+  }
+  
+  private void growArray(int size)
+  {
+    int[] newArray = new int[_size = size];
+    System.arraycopy(_array, 0, newArray, 0, _free);
+    _array = newArray;
+  }
+
+  public int popLast() {
+    return _array[--_free];
+  }
+  
+  public int cardinality() {
+    return _free;
+  }
+  
+  public void toDifferences(IntegerArray result)
+  {
+    if (result._size < _size)
+      result.growArray(_size);
+    if ((result._free = _free) > 0)
+      {
+	result._array[0] = _array[0];
+	for (int i = 1; i < _free; i++)
+	  result._array[i] = _array[i] - _array[i - 1];
+      }
+  }
+  
+  public int indexOf(int value)
+  {
+    int i = 0, j = _free, k;
+    while (i <= j)
+      if (_array[k = (i + j)/2] < value)
+	i = k + 1;
+      else if (value < _array[k])
+	j = k - 1;
+      else
+	return k;
+    return -1;
+  }
+  
+  public void print(java.io.PrintStream out)
+  {
+    for (int i = 0; i < _free - 1; i++)
+      {
+	out.print(_array[i]);
+	out.print(' ');
+      }
+    out.println(_array[_free - 1]);
+  }
+}
diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/LiteMorph.java b/jhMaster/JSearch/client/com/sun/java/help/search/LiteMorph.java
new file mode 100644
index 0000000000000000000000000000000000000000..eeff2b6f71dbebcfd617bdb534bb34c890da52a5
--- /dev/null
+++ b/jhMaster/JSearch/client/com/sun/java/help/search/LiteMorph.java
@@ -0,0 +1,276 @@
+/*
+ * @(#)LiteMorph.java	1.7 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @(#) LiteMorph.java 1.7 - last change made 10/30/06
+ */
+
+package com.sun.java.help.search;
+
+import java.io.*;
+import java.util.StringTokenizer;
+import java.util.Vector;
+import java.util.Hashtable;
+import java.util.Enumeration;
+
+/**
+ * This class will generate an array of morphological variants of a word
+ * to use in search-and-retrieval applications where a user wants to find 
+ * other words morphologically related to words in a query.  For example, 
+ * a request such as "electrical fixtures" should also retrieve "electric
+ * fixtures," "electrical fixture," etc.  Given a word of a query, these 
+ * rules generate alternative variations of that word that should also be 
+ * considered.  This generation of variant forms of a word fills a role 
+ * similar to that often filled by the use of wild card characters or by 
+ * stemming rules that produce truncated stems in traditional information
+ * retrieval systems.  The approach of generating alternative variations
+ * has advantages over a truncated stemming approach for many applications,
+ * because it does not require stemming operations during the indexing
+ * process, does not require extra indexing space for stems, nor does it
+ * lose information by storing only stems.  Rather, the variation rules
+ * are applied to the query to produce additional forms to check against
+ * the index.
+ * <p>
+ * Compared to the use of wild card characters, this approach has two 
+ * advantages: first, it does not require the user to think about where 
+ * the wild cards should be placed, and secondly, it deals with irregular
+ * variations such as irregular verbs (e.g., "break," "broke," "broken"),
+ * and with stem ending effects such as silent e's and doubling of final 
+ * consonants (e.g., "dig," "digs," "digging").  The rules presented here, 
+ * together with a table of exceptions, provided at the end, deal with 
+ * a wide range of such effects, without requiring any more attention on 
+ * the part of the user than to turn on the facility.
+ * <p>
+ * These rules generate regular morphological variants of words using the 
+ * suffixes s, er, ers, est, ed, ing, ly, ful, less, ness, and ment.  Rules 
+ * are included for dealing with some words ending in -ize, -ise, -ic and 
+ * -ical, and for some words requiring irregular forms, such as -leaf and
+ * -man compounds (flyleaf, footman), and Latin words ending in -um and -a, 
+ * such as datum.  The rules are supplemented by a list of exceptions for
+ * words that do not inflect regularly.  They are not intended to apply to
+ * function words or to proper names.  When expanding queries, you may not
+ * want to apply them to capitalized words or to hyphenated words like
+ * day-to-day and low-level.
+ * <p>
+ * The rules treat almost all words as if they were multiply meaningful
+ * as nouns, verbs, and adjectives.  Hence, the rules will often generate
+ * spurious forms that should never occur in a text -- e.g., fix ->
+ * fixest, happy -> happied.  The rules are suitable for applications
+ * such as searching text using inverted files, where a quick test
+ * suffices to determine that a given candidate does not occur in the
+ * corpus.  In such applications, it is preferable to overgenerate
+ * candidates than to miss possible retrievals.
+ * <p>
+ * The program uses rules developed by W. A. Woods and Ellen Hays in 1992.
+ * An original C program for using them was developed by Jacek Ambroziak
+ * and was included in Sun's SearchIt product.
+ *
+ * @author Roger D. Brinkley
+ * @author W. A. Woods
+ * @author Jacek Ambroziak
+ * @version	1.7	10/30/06
+ * 
+ * @see Rule
+ */
+
+public abstract class LiteMorph {
+
+    protected static Vector variants;
+    protected static Hashtable rulesTable;
+    protected static Hashtable blockedVariants;
+    protected static Hashtable exceptions;
+
+    public LiteMorph() {
+	initialize();
+    }
+
+
+    public static LiteMorph getMorph() {
+	return null;
+    }
+
+    /**
+     * Subclasses of this class (generally locale specific)
+     * need to set up exceptions and rules. At a minium 
+     * implementations
+     * need to initialize the size of the exceptions HashTable
+     * and the establish the rules HashTable.
+     * Implementations have the option of filling exceptions
+     * directly in this method or calling intialize(String []).
+     * After initialization the exceptionTable shoudl be garbage
+     * collected
+     */
+    protected abstract void initialize();
+
+    /**
+     * One time initialization of exceptions Hashtable using an
+     * array of Strings. Each String is a list of variation groups.
+     * The words in the groups are  space delimited. Any matching
+     * word in the exceptions will cause all of the words in the
+     * group to be added to the variant list
+     */
+    protected void initialize (String [] exceptionTable) {
+
+	// Firewall
+	if (exceptions == null || exceptionTable == null) {
+	    return;
+	}
+	String tempWord, tempVal;
+	for (int i = 0; i < exceptionTable.length; i++) {
+	    StringTokenizer tokens = new StringTokenizer(exceptionTable[i], " ");
+	    while (tokens.hasMoreTokens()) {
+		tempWord = tokens.nextToken();
+		tempVal = (String)exceptions.get(tempWord);
+		if (tempVal == null) {
+		    exceptions.put(tempWord, exceptionTable[i]);
+		} else {
+		    //the same form can occur in several groups that must be appended
+		    exceptions.put(tempWord, tempVal + " " + exceptionTable[i]);
+		}
+	    }
+	}
+    }
+
+    /**
+     * Get the variants of given word. This is locale
+     * specific variants of a word as supplied by the locale
+     * implementation of this class
+     * 
+     * @return String[] an array of words that are variations of word
+     */
+    public synchronized String[] variantsOf(String word) {
+
+	// intialize variants and blockedVariants
+	variants = new Vector();
+	blockedVariants = new Hashtable ();
+	// this blocks adding the input word itself
+	blockedVariants.put(word, word);
+	    
+	    // Go get the morphological variantes of the word.
+	morphWord(word, 0);
+	    
+	// don't need this anymore; release it for gc
+	blockedVariants = null; 
+	String[] result = new String[variants.size()];
+	variants.copyInto(result);
+	//release this for garbage collection
+	variants = null;
+	return result;
+    }
+  
+    /**
+     * Morph the word into other words if possible
+     */
+    protected void morphWord(String word, int depth) {
+
+	debug(" analyzing: " +word+" at depth "+depth);
+
+	if (depth > 2)
+	    return;
+
+	// if a word is found among exceptions, don't try rules
+
+	String exceptionList = (String)exceptions.get(word);
+	if (exceptionList == null) {
+	    exceptionList = "";
+	}
+	if (exceptionList.length() > 0) {
+	    StringTokenizer tokens = new StringTokenizer(exceptionList, " ");
+	    while (tokens.hasMoreTokens())
+		addVariant(tokens.nextToken());
+	    debug("   "+word+": found match in exceptions -- "+
+		  exceptionList+", at depth "+depth);
+	    return;
+	}
+    
+	if (word.indexOf("-") >= 0)
+	    return;
+	//don't apply rules to words with internal hyphens (but check exceptions)
+
+	Rule[] rules = null;
+	int skipnum = 0;
+
+	// See if the word ends with one of the keys in the rulesTable
+	Enumeration keys = rulesTable.keys();
+	while (keys.hasMoreElements()) {
+	    String key = (String) keys.nextElement();
+	    if (word.endsWith(key) && !key.equals("default")) {
+		rules = (Rule[]) rulesTable.get(key);
+		skipnum = key.length();
+		break;
+	    }
+	}
+	if (rules == null) {
+	    // no match try to get the "default" rules.
+	    rules = (Rule[]) rulesTable.get("default");
+	    skipnum = 0;
+	}
+
+
+	for (int i = 0; i < rules.length; i++) {
+	    debug("  "+word+": trying rule: " + rules[i]+
+		  ", at depth "+depth);
+	    String [] results = rules[i].match(word, depth, skipnum);
+	    if (results.length > 0) {
+		debug("  "+word+": found match for: "+rules[i]+
+		      ", at depth "+depth);
+		addVariant(word); //do this here -- i.e., only when a rule matches
+		for (int j=0; j < results.length; j++) {
+		    addVariant(results[j]);
+		}
+		break;
+	    }
+	}
+    }
+  
+    /**
+     * Add the variant of the word to the list of words
+     */
+    private void addVariant(String word) {
+	if (blockedVariants.get(word) == null) { // word is not blocked
+	    variants.addElement(word);
+	    blockedVariants.put(word, word); // block it from being added again
+	}
+    }
+  
+    /**
+     * Convenience method for creating Rules
+     */
+    protected static Rule r(String expression, String expansions, LiteMorph morph) {
+	return new Rule(expression, expansions, morph);
+    }
+
+    /**
+     * For printf debugging.
+     */
+    private static final boolean debugFlag = false;
+    private static void debug(String str) {
+        if( debugFlag ) {
+            System.out.println("LiteMorph: " + str);
+        }
+    }
+}
diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/LiteMorph_en.java b/jhMaster/JSearch/client/com/sun/java/help/search/LiteMorph_en.java
new file mode 100644
index 0000000000000000000000000000000000000000..c7150e562d8b0794cdfb22d4528d20a4e4a34ae8
--- /dev/null
+++ b/jhMaster/JSearch/client/com/sun/java/help/search/LiteMorph_en.java
@@ -0,0 +1,1578 @@
+/*
+ * @(#)LiteMorph_en.java	1.6 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @(#) LiteMorph_en.java 1.6 - last change made 10/30/06
+ */
+
+package com.sun.java.help.search;
+
+
+import java.io.*;
+import java.util.StringTokenizer;
+import java.util.Vector;
+import java.util.Hashtable;
+
+/**
+ * This is the English version of LiteMorph
+ *
+ * @see LiteMorph
+ */
+public class LiteMorph_en extends LiteMorph{
+
+
+    private static LiteMorph morph = new LiteMorph_en();
+
+    /**
+     * Make this a singleton class
+     */
+    private LiteMorph_en() {
+    }
+
+    /**
+     * Return the LiteMorph for this class
+     */
+    public synchronized static LiteMorph getMorph() {
+	return morph;
+    }
+
+    /**
+     * This is a locale specific intialization.
+     * Create the exceptions HashTable for the size needed.
+     * the call intialize(String []).
+     */
+    protected synchronized void initialize() {
+	if (exceptions != null) {
+	    return;
+	}
+	exceptions = new Hashtable(2800, (float)0.7);
+
+	// The exceptions: 
+	//	current statistics: approx 700 variation groups
+	//		approx 2800 words)
+	String[] exceptionTable = {
+	    "a",
+	    //opt//"aardwolf aardwolves",
+	    "abandoner abandon abandons abandoned abandoning abandonings abandoners",
+	    "abdomen abdomens",
+	    "about",
+	    "above",
+	    //opt//"abscissa abscissas abscissae",
+	    "acid acids acidic acidity acidities",
+	    "across",
+	    "act acts acted acting actor actors",
+	    //opt//"acumen",
+	    "ad ads", 
+	    "add adds added adding addings addition additions adder adders",
+	    //opt//"addendum addenda addendums",
+	    //opt//"adieu adieux adieus",
+	    "advertise advertises advertised advertising advertiser advertisers "
+	    +"advertisement advertisements advertisings",
+	    "after",
+	    "again",
+	    "against",
+	    "ago",
+	    //opt//"agoutis agouti",
+	    //opt//"alias aliases",
+	    "all",
+	    "almost",
+	    "along",
+	    "already",
+	    "also",
+	    "although",
+	    "alumna alumnae alumnus alumni",
+	    //opt//"alveolus alveoli alveolar",
+	    "always",
+	    "amen amens",
+	    "amidships",
+	    "amid amidst",
+	    "among amongst",
+	    //opt//"ampulla ampullae",
+	    //opt//"amygdala amygdalae",
+	    "an",
+	    "analysis analyses",
+	    "and",
+	    //opt//"annulus annuluses annuli annular",
+	    "another other others",
+	    "antenna antennas antennae",
+	    "antitheses antithesis",
+	    "any",
+	    "anyone anybody",
+	    "anything",
+	    "appendix appendixes appendices",
+	    "apropos",
+	    "aquarium aquariums aquaria",
+	    "argument arguments argue argues argued arguing arguings arguer arguers",
+	    "arise arises arose arisen ariser arisers arising arisings",
+	    "around",
+	    "as",
+	    "asbestos",
+	    "at",
+	    "atlas atlases",
+	    //opt//"atrium atriums atria",
+	    "auger augers augered augering augerings augerer augerers",
+	    "augment augments augmented augmenting augmentings augmentation "
+	    +"augmentations augmenter augmenters",
+	    "automata automaton automatons",
+	    "automation automating automate automates automated automatic",
+	    "avoirdupois",
+	    "awake awakes awoke awaked awoken awaker awakers awaking awakings "
+	    +"awakening awakenings",
+	    "away",
+	    "awful awfully awfulness",
+	    "axis axes axises",
+	    "bacillus bacilli",
+	    "bacterium bacteria",
+	    "bad worse worst badly badness",
+	    //opt//"balladier balladiers",
+	    //opt//"bandolier bandoliers",
+	    "bas",
+	    "bases basis",
+	    "bases base based basing basings basely baseness basenesses basement "
+	    +"basements baseless basic basics",
+	    //opt//"bateau bateaux",
+	    //opt//"bathos",
+	    //opt//"bayou bayous",
+	    "be am are is was were been being",
+	    "bear bears bore borne bearing bearings bearer bearers",
+	    "beat beats beaten beating beatings beater beaters",
+	    //opt//"beau beaux beaus",
+	    "because",
+	    "become becomes became becoming",
+	    //opt//"bedesman bedesmans",
+	    "beef beefs beeves beefed beefing",
+	    "beer beers",
+	    "before",
+	    //opt//"beget begets begat begot begotten begetting begettings begetter begetters",
+	    "begin begins began begun beginning beginnings beginner beginners",
+	    "behalf behalves",
+	    "being beings",
+	    "bend bends bent bending bendings bender benders",
+	    "bereave bereaves bereaved bereft bereaving bereavings bereavement "
+	    +"bereavements",
+	    "beside besides",
+	    "best bests bested besting",
+	    "bet bets betting bettor bettors",
+	    "betimes",
+	    "between",
+	    "beyond",
+	    "bid bids bade bidden bidding biddings bidder bidders",
+	    "bier biers",
+	    "bind binds bound binding bindings binder binders",
+	    "bit bits",
+	    "bite bites bit bitten biting bitings biter biters",
+	    "blackfoot blackfeet",
+	    "bleed bleeds bled bleeding bleedings bleeder bleeders",
+	    "blow blows blew blown blowing blowings blower blowers",
+	    "bookshelf bookshelves",
+	    //opt//"borzois borzoi",
+	    "both",
+	    "bound bounds bounded bounding boundings bounder bounders boundless", 
+	    "bourgeois bourgeoisie",
+	    "bra bras",
+	    "brahman brahmans",
+	    "break breaks broke broken breaking breakings breaker breakers",
+	    "breed breeds bred breeding breedings breeder breeders",
+	    "bring brings brought bringing bringings bringer bringers",
+	    //opt//"bronchus bronchi bronchial bronchially",
+	    "build builds built building buildings builder builders",
+	    //opt//"bum bums bummed bumming bummings bummer bummers",
+	    //opt//"bursa bursae bursas bursal",
+	    "bus buses bused bussed busing bussing busings bussings buser busers "
+	    +"busser bussers",
+	    "buss busses bussed bussing bussings busser bussers",
+	    "but",
+	    "buy buys bought buying buyings buyer buyers",
+	    "by",
+	    //opt//"caiman caimans cayman caymans",
+	    //opt//"calculus calculi",
+	    "calf calves calved calving calvings calver calvers",
+	    "can cans canned canning cannings canner canners",
+	    "can could cannot",
+	    //opt//"candelabrum candelabra candelabrums",
+	    "canoes canoe canoed canoeing canoeings canoer canoers",
+	    //opt//"caribou caribous",
+	    "catch catches caught catching catchings catcher catchers",
+	    //opt//"catharsis catharses",
+	    "cement cements cemented cementing cementings cementer cementers",
+	    "cent cents",
+	    "center centers centered centering centerings centerless",
+	    //opt//"chablis",
+	    //opt//"chamois",
+	    //opt//"chapattis chapatti",
+	    //opt//"chateau chateaus chateaux",
+	    //opt//"cherub cherubs cherubim",
+	    "child children childless childish childishly",
+	    "choose chooses chose chosen choosing choosings chooser choosers",
+	    //opt//"cicatrix cicatrices cicatricial cicatricose cicatrize cicatrizes "
+	    //opt//+"cicatrized cicatrizing cicatrizings cicatrization cicatrixes",
+	    //opt//"clement",
+	    //opt//"cliches cliche",
+	    "cling clings clung clinging clingings clinger clingers",
+	    //opt//"codex codices",
+	    //opt//"cognomen",
+	    "colloquium colloquia colloquiums",
+	    //opt//"colossus colossi colossuses",
+	    "come comes came coming comings comer comers",
+	    "comment comments commented commenting commentings commenter commenters",
+	    "compendium compendia compendiums",
+	    "complement complements complemented complementing complementings "
+	    +"complementer complementers complementary",
+	    "compliment compliments complimented complimenting complimentings "
+	    +"complimenter complimenters complimentary",
+	    "concerto concertos concerti",
+	    "condiment condiments",
+	    //opt//"continuum continua continuums",
+	    "corps",
+	    //opt//"corrigendum corrigenda",
+	    "cortex cortices cortexes cortical",
+	    "couscous",
+	    "creep creeps crept creeping creepings creeper creepers creepy",
+	    "crisis crises",
+	    "criterion criteria criterial",
+	    "cryptanalysis cryptanalyses",
+	    "curriculum curricula curriculums curricular",
+	    //opt//"cyclamen cyclamens",
+	    //opt//"czech czechs czechoslovakia czechoslovak czechoslovaks czechoslovakian "
+	    //opt//+"czechoslovakians Czech Czechs Czechoslovakia Czechoslovak Czechoslovaks "
+	    //opt//+"Czechoslovakian Czechoslovakians",
+	    //opt//"dais daises",
+	    "datum data",
+	    "day days daily",
+	    "deal deals dealt dealing dealings dealer dealers",
+	    "decrement decrements decremented decrementing decrementings "
+	    +"decrementer decrementers decremental",
+	    "deer deers",
+	    //opt//"deixis deixes",
+	    "demented dementia",
+	    "desideratum desiderata",
+	    //opt//"desman desmans",
+	    "diagnosis diagnoses diagnose diagnosed diagnosing diagnostic",
+	    "dialysis dialyses",
+	    "dice dices diced dicing dicings dicer dicers",
+	    "die dice",
+	    "die dies died dying dyings",
+	    "dig digs dug digging diggings digger diggers",
+	    "dive dives diver divers dove dived diving divings",
+	    "divest divests divester divesters divested divesting divestings "
+	    +"divestment divestments",
+	    "do does did done doing doings doer doers",
+	    "document documents documented documenting documentings documenter "
+	    +"documenters documentation documentations documentary",
+	    //opt//"dodecahedron dodecahedra dodecahedrons",
+	    "doe does",
+	    //opt//"dormouse dormice",
+	    "dove doves",
+	    "downstairs",
+	    "dozen",
+	    "draw draws drew drawn drawing drawings drawer drawers",
+	    "drink drinks drank drunk drinking drinkings drinker drinkers",
+	    "drive drives drove driven driving drivings driver drivers driverless",
+	    "due dues duly",
+	    "during",
+	    "e",
+	    "each",
+	    "eager eagerer eagerest eagerly eagerness eagernesses",
+	    "early earlier earliest",
+	    "easement easements",
+	    "eat eats ate eaten eating eatings eater eaters",
+	    "effluvium effluvia",
+	    "either",
+	    "element elements elementary",
+	    "elf elves elfen",
+	    "ellipse ellipses elliptic elliptical elliptically",
+	    "ellipsis ellipses elliptic elliptical elliptically",
+	    "else",
+	    "embolus emboli embolic embolism",
+	    "emolument emoluments",
+	    "emphasis emphases",
+	    "employ employs employed employing employer employers employee "
+	    +"employees employment employments employable",
+	    "enough",
+	    "equilibrium equilibria equilibriums",
+	    "erratum errata",
+	    "ever",
+	    "every",
+	    "everything",
+	    //opt//"exegeses exegesis",
+	    "exotic exotically exoticness exotica",
+	    "experiment experiments experimented experimenting experimentings "
+	    +"experimenter experimenters experimentation experimental",
+	    "extra extras",
+	    //opt//"extremum extrema extremums extreme extremely extremeness extremist extremism",
+	    "fall falls fell fallen falling fallings faller fallers",
+	    "far farther farthest",
+	    "fee fees feeless",
+	    "feed feeds fed feeding feedings feeder feeders",
+	    "feel feels felt feeling feelings feeler feelers",
+	    "ferment ferments fermented fermenting fermentings fermentation "
+	    +"fermentations fermenter fermenters",
+	    "few fewer fewest",
+	    //opt//"fez fezzes fezes",
+	    "fight fights fought fighting fightings fighter fighters",
+	    "figment figments",
+	    "filament filaments",
+	    "find finds found finding findings finder finders",
+	    "firmament firmaments",
+	    "flee flees fled fleeing fleeings",
+	    "fling flings flung flinging flingings flinger flingers",
+	    "floe floes",
+	    "fly flies flew flown flying flyings flier fliers flyer flyers",
+	    "focus foci focuses focused focusing focusses focussed focussing focuser focal",
+	    "foment foments fomented fomenting fomentings fomenter fomenters",
+	    "foot feet",
+	    "foot foots footed footing footer footers",
+	    "footing footings footer footers",
+	    "for",
+	    "forbid forbids forbade forbidden forbidding forbiddings forbidder forbidders",
+	    "foresee foresaw foreseen foreseeing foreseeings foreseer foreseers",
+	    "forest forests forester foresting forestation forestations",
+	    "forget forgets forgot forgotten forgetting forgettings forgetter "
+	    +"forgetters forgetful",
+	    "forsake forsakes forsook forsaken forsaking forsakings forsaker forsakers",
+	    "found founds founded founding foundings founder founders",
+	    "fragment fragments fragmented fragmenting fragmentings fragmentation "
+	    +"fragmentations fragmenter fragmenters",
+	    "free frees freer freest freed freeing freely freeness freenesses",
+	    "freeze freezes froze frozen freezing freezings freezer freezers",
+	    "from",
+	    "full fully fuller fullest",
+	    "fuller fullers full fulls fulled fulling fullings",
+	    "fungus fungi funguses fungal",
+	    "gallows",
+	    "ganglion ganglia ganglions ganglionic",
+	    "garment garments",
+	    "gas gasses gassed gassing gassings gasser gassers",
+	    "gas gases gasses gaseous gasless",
+	    "gel gels gelled gelling gellings geller gellers",
+	    //opt//"geneses genesis",
+	    "german germans germanic germany German Germans Germanic Germany",
+	    "get gets got gotten getting gettings getter getters",
+	    "give gives gave given giving givings giver givers",
+	    "gladiolus gladioli gladioluses gladiola gladiolas gladiolae",
+	    "glans glandes",
+	    //opt//"glissando glissandi glissandos",
+	    "gluiness gluey glue glues glued gluing gluings gluer gluers",
+	    //opt//"glum glummer glummest",
+	    "go goes went gone going goings goer goers",
+	    "godchild godchildren",
+	    "good better best goodly goodness goodnesses",
+	    "goods",
+	    "goose geese",
+	    "goose gooses goosed goosing goosings gooser goosers",
+	    "grandchild grandchildren",
+	    "grind grinds ground grinding grindings grinder grinders",
+	    "ground grounds grounded grounding groundings grounder grounders groundless",
+	    "grow grows grew grown growing growings grower growers growth",
+	    "gum gums gummed gumming gummings gummer gummers",
+	    "half halves",
+	    "halve halves halved halving halvings halver halvers",
+	    "hang hangs hung hanged hanging hangings hanger hangers",
+	    //opt//"hanuman hanumans",
+	    "have has had having havings haver havers",
+	    "he him his himself",
+	    "hear hears heard hearing hearings hearer hearers",
+	    "here",
+	    //opt//"herr herren Herr Herren",
+	    //opt//"hiatus hiatuses",
+	    "hide hides hid hidden hiding hidings hider hiders",
+	    //opt//"hie hies hied hieing hying hieings hyings hier hiers",
+	    "hippopotamus hippopotami hippopotamuses", 
+	    "hold holds held holding holdings holder holders",
+	    "honorarium honoraria honorariums",
+	    "hoof hoofs hooves hoofed hoofing hoofer hoofers",
+	    "how",
+	    "hum hums hummed humming hummings hummer hummers",
+	    "hymen hymens hymenal",
+	    "hypotheses hypothesis hypothesize hypothesizes hypothesized hypothesizer "
+	    +"hypothesizing hypothetical hypothetically",
+	    "i",
+	    //opt//"icosahedron icosahedra icosahedrons",
+	    "if iffy",
+	    "impediment impediments",
+	    "implement implements implemented implementing implementings implementation "
+	    +"implementations implementer implementers",
+	    "imply implies implied implying implyings implier impliers",
+	    "in inner",
+	    "inclement",
+	    "increment increments incremented incrementing incrementings incrementer "
+	    +"incrementers incremental incrementally",
+	    "index indexes indexed indexing indexings indexer indexers",
+	    "index indexes indices indexical indexicals",
+	    "indoor indoors",
+	    "instrument instruments instrumented instrumenting instrumentings "
+	    +"instrumenter instrumenters instrumentation instrumentations instrumental",
+	    "integument integumentary",
+	    "into",
+	    "it its itself",
+	    "july julys",
+	    "keep keeps kept keeping keepings keeper keepers",
+	    "knife knifes knifed knifing knifings knifer knifers",
+	    "knife knives",
+	    "know knows knew known knowing knowings knower knowers knowledge",
+	    "lament laments lamented lamenting lamentings lamentation lamentations "
+	    +"lamenter lamenters lamentable lamentably",
+	    "larva larvae larvas larval",
+	    "late later latest lately lateness",
+	    "latter latterly",
+	    "lay lays laid laying layer layers",
+	    "layer layers layered layering layerings",
+	    "lead leads led leading leadings leader leaders leaderless",
+	    "leaf leafs leafed leafing leafings leafer leafers",
+	    "leaf leaves leafless",
+	    "leave leaves left leaving leavings leaver leavers",
+	    //opt//"legume legumes",
+	    "lend lends lent lending lendings lender lenders",
+	    "less lesser least",
+	    "let lets letting lettings",
+	    //opt//"libretto librettos libretti",
+	    "lie lies lay lain lying lier liers",
+	    "lie lies lied lying liar liars",
+	    "life lives lifeless",
+	    "light lights lit lighted lighting lightings lightly lighter lighters "
+	    +"lightness lightnesses lightless",
+	    "likely likelier likeliest",
+	    "limen limens",
+	    "lineament lineaments",
+	    "liniment liniments",
+	    "live alive living",
+	    "live lives lived living livings",
+	    "liver livers",
+	    //opt//"llamela llamelae",
+	    "loaf loafs loafed loafing loafings loafer loafers",
+	    "loaf loaves",
+	    //opt//"locus loci",
+	    "logic logics logical logically",
+	    "lose loses lost losing loser losers loss losses",
+	    "louse lice",
+	    "lumen lumens",
+	    "make makes made making makings maker makers",
+	    "man mans manned manning mannings",
+	    "man men",
+	    "manly manlier manliest manliness manful manfulness manhood",
+	    "manic manically",
+	    "manner manners mannered mannerly mannerless mannerful",
+	    //opt//"mantra mantras",
+	    "many",
+	    "matrix matrices matrixes",
+	    "may might",
+	    "maximum maxima maximums maximal maximize maximizes maximized maximizing",
+	    "mean means meant meaning meanings meaningless meaningful",
+	    "mean meaner meanest meanly meanness meannesses",
+	    "median medians medianly medial",
+	    "medium media mediums",
+	    "meet meets met meeting meetings",
+	    "memorandum memoranda memorandums",
+	    "mere merely",
+	    "metal metals metallic",
+	    "might mighty mightily",
+	    //opt//"milieu milieus milieux",
+	    "millenium millennia milleniums millennial",
+	    "mine mines mined mining minings miner miners",
+	    "mine my our ours",
+	    "minimum minima minimums minimal",
+	    "minus minuses",
+	    "miscellaneous miscellanea miscellaneously miscellaneousness miscellany",
+	    //opt//"modulus moduli",
+	    "molest molests molested molesting molestings molester molesters",
+	    "moment moments",
+	    "monument monuments monumental",
+	    //opt//"mooncalf mooncalves",
+	    "more most",
+	    "mouse mice mouseless",
+	    "much",
+	    "multiply multiplies multiplier multipliers multiple multiples "
+	    +"multiplying multiplyings multiplication multiplications",
+	    "mum mums mummed mumming mummings mummer mummers",
+	    "must musts",
+	    "neither",
+	    "nemeses nemesis",
+	    "neurosis neuroses neurotic neurotics",
+	    "nomen",
+	    "none",
+	    "nos no noes",
+	    "not",
+	    "nothing nothings nothingness",
+	    "now",
+	    "nowadays",
+	    "nucleus nuclei nucleuses nuclear",
+	    //opt//"nucleolus nucleoli nucleolar",
+	    "number numbers numbered numbering numberings numberless",
+	    "nutriment nutriments nutrient nutrients nutrition nutritions",
+	    "oasis oases",
+	    //opt//"octahedron octahedra octahedrons",
+	    "octopus octopi octopuses",
+	    "of",
+	    "off",
+	    "offer offers offered offering offerings offerer offerers offeror offerors",
+	    "often",
+	    "oftentimes",
+	    "ointment ointments",
+	    "omen omens",
+	    "on",
+	    "once",
+	    "only",
+	    //opt//"operetta operettas operetti",
+	    "ornament ornaments ornamented ornamenting ornamentings ornamentation "
+	    +"ornamenter ornamenters ornamental",
+	    "outdoor outdoors",
+	    "outlay outlays",
+	    "outlie outlies outlay outlied outlain outlying outlier outliers",
+	    "ovum ova",
+	    "ox oxen",
+	    //opt//"palazzo palazzi palazzos",
+	    "parentheses parenthesis",
+	    "parliament parliaments parliamentary",
+	    "passerby passer-by passersby passers-by",
+	    "past pasts",
+	    //opt//"patois",
+	    "pay pays paid paying payings payer payers payee payees payment payments",
+	    //opt//"pediment pediments",
+	    "per",
+	    "perhaps",
+	    "person persons people",
+	    //opt//"phallus phalli phalluses phallic",
+	    //opt//"phylum phyla phylums",
+	    "phenomenon phenomena phenomenal",
+	    //opt//"phosphorus",
+	    "pi",
+	    "picnic picnics picnicker picnickers picnicked picnicking picnickings",
+	    "pigment pigments pigmented pigmenting pigmentings pigmenter pigmenters "
+	    +"pigmentation pigmentations",
+	    "please pleases pleased pleasing pleasings pleaser pleasers pleasure "
+	    +"pleasures pleasuring pleasurings pleasant pleasantly pleasureless "
+	    +"pleasureful",
+	    "plus pluses plusses",
+	    "polyhedra polyhedron polyhedral",
+	    "priest priests priestly priestlier priestliest priestliness priestless",
+	    "prognosis prognoses",
+	    "prostheses prosthesis",
+	    "prove proves proved proving provings proofs proof prover provers provable",
+	    "psychosis psychoses psychotic psychotics",
+	    //opt//"pupa pupae pupas pupal",
+	    "qed",
+	    "quiz quizzes quizzed quizzing quizzings quizzer quizzers",
+	    "raiment",
+	    "rather",
+	    "re",
+	    "real really",
+	    "redo redoes redid redone redoing redoings redoer redoers",
+	    "regiment regiments regimented regimenting regimenter regimenters "
+	    +"regimentation regimental",
+	    "rendezvous",
+	    "requiz requizzes requizzed requizzing requizzings requizzer requizzers",
+	    "ride rides rode ridden riding ridings rider riders rideless",
+	    "ring rings rang rung ringing ringings ringer ringers ringless",
+	    "rise rises rose risen rising risings riser risers",
+	    //opt//"roof roofs roofed roofing roofings roofer roofers roofless",
+	    "rose roses",
+	    "rudiment rudiments rudimentary",
+	    "rum rums rummed rumming rummings rummer rummers",
+	    "run runs ran running runnings runner runners",
+	    "sacrament sacraments sacramental",
+	    "same sameness",
+	    "sans",
+	    "saw saws sawed sawn sawing sawings sawyer sawyers",
+	    "say says said saying sayings sayer sayers",
+	    "scarf scarfs scarves scarfless",
+	    "schema schemata schemas",
+	    //opt//"scherzo scherzi scherzos",
+	    //opt//"scrotum scrota scrotums",
+	    "sediment sediments sedimentary sedimentation sedimentations",
+	    "see sees saw seen seeing seeings seer seers",
+	    "seek seeks sought seeking seekings seeker seekers",
+	    "segment segments segmented segmenting segmentings segmenter segmenters "
+	    +"segmentation segmentations",
+	    "self selves selfless",
+	    "sell sells sold selling sellings seller sellers",
+	    "semen",
+	    "send sends sent sending sendings sender senders",
+	    "sentiment sentiments sentimental",
+	    //opt//"seraph seraphs seraphim",
+	    "series",
+	    "set sets setting settings",
+	    "several severally",
+	    "sew sews sewed sewn sewing sewings sewer sewers",
+	    "sewer sewers sewerless",
+	    "shake shakes shook shaken shaking shakings shaker shakers",
+	    "shall should",
+	    "shaman shamans",
+	    "shave shaves shaved shaven shaving shavings shaver shavers shaveless",
+	    "she her hers herself",
+	    "sheaf sheaves sheafless",
+	    "sheep",
+	    "shelf shelves shelved shelfing shelvings shelver shelvers shelfless",
+	    "shine shines shined shone shining shinings shiner shiners shineless",
+	    "shoe shoes shoed shod shoeing shoeings shoer shoers shoeless",
+	    "shoot shoots shot shooting shootings shooter shooters",
+	    "shot shots",
+	    "show shows showed shown showing showings shower showers",
+	    "shower showers showery showerless",
+	    "shrink shrinks shrank shrunk shrinking shrinkings shrinker shrinkers "
+	    +"shrinkable",
+	    "sideways",
+	    //opt//"simplex simplexes simplices",
+	    "simply simple simpler simplest",
+	    "since",
+	    "sing sings sang sung singing singings singer singers singable",
+	    "sink sinks sank sunk sinking sinkings sinker sinkers sinkable",
+	    "sit sits sat sitting sittings sitter sitters",
+	    "ski skis skied skiing skiings skier skiers skiless skiable",
+	    "sky skies",
+	    "slay slays slew slain slaying slayings slayer slayers",
+	    "sleep sleeps slept sleeping sleepings sleeper sleepers sleepless",
+	    "so",
+	    "some",
+	    "something",
+	    "sometime sometimes",
+	    "soon",
+	    "spa spas",
+	    "speak speaks spoke spoken speaking speakings speaker speakers",
+	    "species specie",
+	    "spectrum spectra spectrums",
+	    "speed speeds sped speeded speeding speedings speeder speeders",
+	    "spend spends spent spending spendings spender spenders spendable",
+	    "spin spins spun spinning spinnings spinner spinners",
+	    "spoke spokes",
+	    "spring springs sprang sprung springing springings springer springers "
+	    +"springy springiness",
+	    "staff staffs staves staffed staffing staffings staffer staffers",
+	    "stand stands stood standing standings",
+	    "stasis stases",
+	    "steal steals stole stolen stealing stealings stealer stealers",
+	    "stick sticks stuck sticking stickings sticker stickers",
+	    "stigma stigmata stigmas stigmatize stigmatizes stigmatized stigmatizing",
+	    "stimulus stimuli",
+	    "sting stings stung stinging stingings stinger stingers",
+	    "stink stinks stank stunk stinking stinkings stinker stinkers",
+	    "stomach stomachs",
+	    "stratum strata stratums",
+	    "stride strides strode stridden striding stridings strider striders",
+	    "string strings strung stringing stringings stringer stringers stringless",
+	    "strive strives strove striven striving strivings striver strivers",
+	    "strum strums strummed strumming strummings strummer strummers strummable",
+	    //opt//"stylus styli styluses",
+	    //opt//"succubus succubi",
+	    "such",
+	    "suffer suffers suffered suffering sufferings sufferer sufferers sufferable",
+	    "suggest suggests suggested suggesting suggestings suggester suggesters "
+	    +"suggestor suggestors suggestive suggestion suggestions suggestible "
+	    +"suggestable",
+	    "sum sums summed summing summings summer summers",
+	    "summer summers summered summering summerings",
+	    "supplement supplements supplemented supplementing supplementings "
+	    +"supplementation supplementer supplementers supplementary supplemental",
+	    "supply supplies supplied supplying supplyings supplier suppliers",
+	    "swear swears swore sworn swearing swearings swearer swearers",
+	    "sweep sweeps swept sweeping sweepings sweeper sweepers",
+	    "swell swells swelled swollen swelling swellings",
+	    "swim swims swam swum swimming swimmings swimmer swimmers swimable",
+	    "swine",
+	    "swing swings swung swinging swingings swinger swingers",
+	    "syllabus syllabi syllabuses",
+	    "symposium symposia symposiums",
+	    "synapse synapses",
+	    "synapsis synapses",
+	    "synopsis synopses",
+	    "synthesis syntheses",
+	    "tableau tableaux tableaus",
+	    "take takes took taken taking takings taker takers takable",
+	    "teach teaches taught teaching teachings teacher teachers teachable",
+	    "tear tears tore torn tearing tearings tearer tearers tearable",
+	    "tegument teguments",
+	    "tell tells told telling tellings teller tellers tellable",
+	    "temperament temperaments temperamental temperamentally",
+	    "tenement tenements",
+	    //opt//"terminus termini",
+	    //opt//"than thans",
+	    //opt//"that thats",
+	    "the",
+	    "there theres",
+	    "theses thesis",
+	    "they them their theirs themselves",
+	    "thief thieves thieving thievings",
+	    "think thinks thought thinking thinker thinkers thinkable",
+	    "this that these those",
+	    "thought thoughts thougtful thoughtless",
+	    "throw throws threw thrown throwing throwings thrower throwers throwable",
+	    //opt//"thus thuses",
+	    "tic tics",
+	    "tie ties tied tying tyings tier tiers tieable tieless",
+	    "tier tiers tiered tiering tierings tierer tierers",
+	    "to",
+	    "toe toes toed toeing toeings toer toers toeless",
+	    "together togetherness",
+	    "too",
+	    "tooth teeth toothless",
+	    "topaz topazes",
+	    "torment torments tormented tormenting tormentings tormenter tormenters "
+	    +"tormentable",
+	    "toward towards",
+	    "tread treads trod trodden treading treadings treader treaders",
+	    "tread treads treadless retread retreads",
+	    "true truly trueness",
+	    "two twos",
+	    "u",
+	    "under",
+	    "underlay underlays underlaid underlaying underlayings underlayer "
+	    +"underlayers",
+	    "underlie underlies underlay underlain underlying underlier underliers",
+	    "undo undoes undid undone undoing undoings undoer undoers undoable",
+	    "unrest unrestful",
+	    "until",
+	    "unto",
+	    "up",
+	    "upon",
+	    "upstairs",
+	    "use uses user users used using useful useless",
+	    "various variously",
+	    "vehement vehemently vehemence",
+	    "versus",
+	    "very",
+	    "visit visits visited visiting visitings visitor visitors",
+	    "vortex vortexes vortices",
+	    "wake wakes woke waked woken waking wakings waker wakers wakeful "
+	    +"wakefulness wakefulnesses wakeable",
+	    "wear wears wore worn wearing wearings wearer wearers wearable",
+	    "weather weathers weathered weathering weatherly",
+	    "weave weaves wove woven weaving weavings weaver weavers weaveable",
+	    "weep weeps wept weeping weepings weeper weepers",
+	    "wharf wharfs wharves",
+	    //opt//"what whats",
+	    //opt//"when whens",
+	    "where wheres",
+	    "whereas whereases",
+	    "whether whethers",
+	    //opt//"which whiches",
+	    "while whiles whilst whiled whiling",
+	    "whiz whizzes whizzed whizzing whizzings whizzer whizzers",
+	    "who whom whos whose whoses",
+	    "why whys",
+	    "wife wives wifeless",
+	    "will wills willed willing willings willful",
+	    "will would",
+	    "win wins won winning winnings winner winners winnable",
+	    "wind winds wound winding windings winder winders windable",
+	    "wind winds windy windless",
+	    "with",
+	    "within",
+	    "without",
+	    "wolf wolves",
+	    "woman women womanless womanly",
+	    "wound wounds wounded wounding woundings",
+	    "write writes wrote written writing writings writer writers writeable",
+	    "yeses yes",
+	    "yet yets",
+	    "you your yours yourself"};
+
+	initialize(exceptionTable);
+
+	// The rules:
+
+	// For words ending in -s (s-rules):
+
+	Rule[] sRules = {
+	    r(".aeiouy bcdfghjklmnpqrstvwxyz + i n e s s",
+	      "y,ies,ier,iers,iest,ied,ying,yings,ily,inesses,iment,iments,iless,iful",
+	      this),
+	    // 	(e.g., happiness, business)
+
+	    r(".aeiouy + e l e s s",
+	      "e,es,er,ers,est,ed,ing,ings,eing,eings,ely,eness,enesses,ement,ements,"
+	      +"eness,enesses,eful",
+	      this),
+	    // 	(e.g., baseless, shoeless)
+
+	    r("bcdfghjklmnpqrstvwxyz aeiouy bdgklmnprt + l e s s",
+	      "_,s,&er,&ers,&est,&ed,&ing,&ings,ly,ness,nesses,ment,ments,ful",
+	      this),
+	    // 	(e.g., gutless, hatless, spotless)
+
+	    r(".aeiouy + l e s s",
+	      "_,s,er,ers,est,ed,ing,ings,ly,ness,nesses,ment,ments,ful",
+	      this),
+	    // 	(e.g., thoughtless, worthless)
+
+	    r(".aeiouy + e n e s s",
+	      "e,es,er,ers,est,ed,ing,ings,eing,eings,ely,enesses,ement,ements,"
+	      +"eless,eful",
+	      this),
+	    // 	(e.g., baseness, toeness)
+
+	    r(".aeiouy + n e s s",
+	      "_,s,er,ers,est,ed,ing,ings,ly,nesses,ment,ments,less,ful",
+	      this),
+	    // 	(e.g., bluntness, grayness)
+
+	    r(".aeiouy s s +",
+	      "es,er,ers,est,ed,ing,ings,ly,ness,nesses,ment,ments,less,ful",
+	      this),
+	    // 	(e.g., albatross, kiss)
+
+	    r(".aeiouy o u s +",
+	      "ly,ness",
+	      this),
+	    // 	(e.g., joyous, fractious, gaseous)
+
+	    r("+ i e s",
+	      "y,ie,yer,yers,ier,iers,iest,ied,ying,yings,yness,iness,ieness,ynesses,"
+	      +"inesses,ienesses,iment,iement,iments,iements,yless,iless,ieless,yful,"
+	      +"iful,ieful",
+	      this),
+	    // 	(e.g., tries, unties, jollies, beauties)
+
+	    r(".aeiouy + s i s",
+	      "ses,sises,sisness,sisment,sisments,sisless,sisful",
+	      this),
+	    // 	(e.g., crisis, kinesis)
+
+	    r(".aeiouy i s +",
+	      "es,ness,ment,ments,less,ful",
+	      this),
+	    // 	(e.g., bronchitis, bursitis)
+
+	    r(".aeiouy c h + e s",
+	      "_,e,er,ers,est,ed,ing,ings,ly,ely,ness,eness,nesses,enesses,ment,"
+	      +"ement,ments,ements,less,eless,ful,eful",
+	      this),
+
+	    r(".aeiouy s h + e s",
+	      "_,e,er,ers,est,ed,ing,ings,ly,ely,ness,eness,nesses,enesses,ment,"
+	      +"ement,ments,ements,less,eless,ful,eful",
+	      this),
+
+	    r(".aeiouy bcdfghjklmnpqrstvwxz + i z e s",
+	      "ize,izer,izers,ized,izing,izings,ization,izations,"
+	      +"ise,ises,iser,isers,ised,ising,isings,isation,isations",
+	      this),
+	    // 	(e.g., tokenizes) // adds British variations
+
+	    r(".aeiouy bcdfghjklmnpqrstvwxz + i s e s",
+	      "ize,izes,izer,izers,ized,izing,izings,ization,izations,"
+	      +"ise,iser,isers,ised,ising,isings,isation,isations",
+	      this),
+	    // 	(e.g., tokenises) // British variant  // ~expertise
+
+	    r(".aeiouy jsxz + e s",
+	      "_,e,er,ers,est,ed,ing,ings,ly,ely,ness,eness,nesses,enesses,ment,"
+	      +"ement,ments,ements,less,eless,ful,eful",
+	      this),
+	    // 	(e.g., aches, arches)
+	    //  v is not in this set because ve words can keep the e before ing
+	    //  NB: we are not handling -is plurals like crises
+
+	    r(".aeiouy d g + e s",
+	      "e,er,ers,est,ed,ing,ings,ely,eness,enesses,ment,ments,ement,ements,"
+	      +"eless,eful",
+	      this),
+	    // 	(e.g., judges, abridges)
+
+	    r("e + s",
+	      "*_",
+	      this),
+	    // 	(e.g., trees, races, likes, agrees)
+	    //  covers all other -es words
+
+	    r("s e g m e n t + s",
+	      "*_",
+	      this),
+	    // 	(e.g., segments, bisegments, cosegments)
+
+	    r("p i g m e n t + s",
+	      "*_",
+	      this),
+	    // 	(e.g., pigments, depigments, repigments)
+
+	    r(".aeiouy d g + m e n t s",
+	      "ment,*ment",
+	      this),
+	    // 	(e.g., judgments, abridgments)
+
+	    r(".aeiouy bcdfghjklmnpqrstvwxyz i m e n t + s",
+	      "*_",
+	      this),
+	    // 	(e.g., merriments, embodiments)
+	    //  -iment in turn will generate y and *y (redo y)
+
+	    r(".aeiouy m e n t + s",
+	      "*_",
+	      this),
+	    // 	(e.g., atonements, entrapments)
+
+	    r(".aeiouy e r + s",
+	      "*_",
+	      this),
+	    // 	(e.g., viewers, meters, traders, transfers)
+
+	    r(".aeiouy bcdfghjklmnpqrstvwxyz aeiouy bdglmnprt + s",
+	      "*_",
+	      this),
+	    // 	(e.g., unflags)
+	    //  polysyllables
+
+	    r("bcdfghjklmnpqrstvwxyz aeiouy bdglmnprt + s",
+	      "*_",
+	      this),
+	    // 	(e.g., frogs)
+	    //  monosyllables
+
+	    r(".aeiouy i n g + s",
+	      "*_",
+	      this),
+	    // 	(e.g., killings, muggings)
+
+	    r(".aeiouy l l + s",
+	      "*_",
+	      this),
+	    // 	(e.g., hulls, tolls)
+
+	    r(".bcdfghjklmnpqrstvwxyz + s",
+	      "*_",
+	      this),
+	    // 	(e.g., beads, toads, zoos)
+	};
+
+	// For words ending in -e (e-rules):
+
+	Rule[] eRules = {
+	    r(".aeiouy bcdfghjklmnpqrstvwxyz l + e",
+	      "es,er,ers,est,ed,ing,ings,y,ely,eness,enesses,ement,ements,eless,eful",
+	      this),
+	    // 	(e.g., able, abominable, fungible, table, enable, idle, subtle)
+
+	    r("+ i e",
+	      "ies,ier,iers,iest,ied,ying,yings,iely,ieness,ienesses,iement,iements,"
+	      +"ieless,ieful",
+	      this),
+	    // 	(e.g., bookie, magpie, vie)
+
+	    r("y e +",
+	      "s,r,rs,st,d,ing,ings,ly,ness,nesses,ment,ments,less,ful",
+	      this),
+	    // 	(e.g., dye, redye, redeye)
+
+	    r(".aeiouy d g + e",
+	      "es,er,ers,est,ed,ing,ings,ely,eness,enesses,ment,ments,less,ful,ement,"
+	      +"ements,eless,eful",
+	      this),
+	    // 	(e.g., judge, abridge)
+
+	    r("u + e",
+	      "es,er,ers,est,ed,ing,ings,eing,eings,ly,ely,eness,enesses,ment,ments,"
+	      +"less,ful,ement,ements,eless,eful",
+	      this),
+	    // 	(e.g., true, due, imbue)
+
+	    r(".aeiouy bcdfghjklmnpqrstvwxz + i z e",
+	      "izes,izer,izers,ized,izing,izings,ization,izations,"
+	      +"ise,ises,iser,isers,ised,ising,isings,isation,isations",
+	      this),
+	    // 	(e.g., tokenize) // adds British variations
+
+	    r(".aeiouy bcdfghjklmnpqrstvwxz + i s e",
+	      "ize,izes,izer,izers,ized,izing,izings,ization,izations,"
+	      +"ises,iser,isers,ised,ising,isings,isation,isations",
+	      this),
+	    // 	(e.g., tokenise) // British variant  // ~expertise
+
+	    r("+ e",
+	      "es,er,ers,est,ed,ing,ings,eing,eings,ely,eness,enesses,ement,ements,"
+	      +"eless,eful",
+	      this),
+	    // 	(e.g., tree, agree, rage, horse, hoarse)
+	};
+
+	// For words ending in -ed (ed-rules):
+  
+	Rule[] edRules = {
+	    r("r e e + d",
+	      "ds,der,ders,ded,ding,dings,dly,dness,dnesses,dment,dments,dless,dful,*_",
+	      this),
+	    // 	(e.g., agreed, freed, decreed, treed)
+
+	    r("e e + d",
+	      "ds,der,ders,ded,ding,dings,dly,dness,dnesses,dment,dments,dless,dful",
+	      this),
+	    // 	(e.g., feed, seed, Xweed)
+
+	    r("bcdfghjklmnpqrstvwxyz + i e d",
+	      "y,ie,ies,ier,iers,iest,ying,yings,ily,yly,iness,yness,inesses,ynesses,"
+	      +"iment,iments,iless,iful,yment,yments,yless,yful",
+	      this),
+	    // 	(e.g., tried)
+
+	    r(".aeiouy .bcdfghjklmnpqrstvwxyz l + l e d",
+	      "_,s,er,ers,est,ing,ings,ly,ness,nesses,ment,ments,less,ful,&,&s,"
+	      +"&er,&ers,&est,&ing,&ings,&y,&ness,&nesses,&ment,&ments,&ful",
+	      this),
+	    // 	(e.g., controlled, fulfilled, rebelled)
+	    //  both double and single l forms
+
+	    r(".aeiouy l + l e d",
+	      "&,&s,&er,&ers,&est,&ing,&ings,&y,&ness,&nesses,&ment,&ments,&ful",
+	      this),
+	    // 	(e.g., pulled, filled, fulled)
+
+	    r(".aeiouy s + s e d",
+	      "&,&es,&er,&ers,&est,&ing,&ings,&ly,&ness,&nesses,&ment,&ments,&less,&ful",
+	      this),
+	    // 	(e.g., hissed, grossed)
+
+	    r("bcdfghjklmnpqrstvwxyz aeiouy bdgklmnprt + & e d",
+	      "_,s,&er,&ers,&est,&ing,&ings,ly,ness,nesses,ment,ments,less,ful",
+	      this),
+	    // 	(e.g., hugged, trekked)
+
+	    r(".aeiouy bcdfghjklmnpqrstvwxz + i z e d",
+	      "izes,izer,izers,ize,izing,izings,ization,izations,"
+	      +"ise,ises,iser,isers,ised,ising,isings,isation,isations",
+	      this),
+	    // 	(e.g., tokenize) // adds British variations
+
+	    r(".aeiouy bcdfghjklmnpqrstvwxz + i s e d",
+	      "ize,izes,izer,izers,ized,izing,izings,ization,izations,"
+	      +"ises,iser,isers,ise,ising,isings,isation,isations",
+	      this),
+	    // 	(e.g., tokenise) // British variant  // ~expertise
+
+	    r(".aeiouy + e d",
+	      "_,e,s,es,er,ers,est,ing,ings,ly,ely,ness,eness,nesses,enesses,"
+	      +"ment,ement,ments,ements,less,eless,ful,eful",
+	      this),
+	    // 	(e.g., spoiled, tooled, tracked, roasted, atoned, abridged)
+
+	    r("e d +",
+	      "s,&er,&ers,&est,&ed,&ing,&ings,ly,ness,nesses,ment,ments,less,ful",
+	      this),
+	    // 	(e.g., bed, sled)
+	    //  words with a single e as the only vowel
+	};
+
+	// For words ending in -er (er-rules):
+
+	Rule[] erRules = {
+	    r("m e t e r +",
+	      "s,er,ers,ed,ing,ings,ly,ness,nesses,ment,ments,less,ful",
+	      this),
+	    // 	(e.g., altimeter, ammeter, odometer, perimeter)
+
+	    r("+ e e r",
+	      "eers,eered,eering,eerings,eerly,eerness,eernesses,eerment,eerments,"
+	      +"eerless,eerful,ee,ees,eest,eed,eeing,eeings,eely,eeness,eenesses,"
+	      +"eement,eements,eeless,eeful,eerer,eerers,eerest",
+	      this),
+	    // 	(e.g., agreer, beer, budgeteer, engineer, freer)
+
+	    r("bcdfghjklmnpqrstvwxyz + i e r",
+	      "y,ie,ies,iest,ied,ying,yings,ily,yly,iness,yness,inesses,ynesses,"
+	      +"yment,yments,yless,yful,iment,iments,iless,iful,iers,iered,"
+	      +"iering,ierings,ierly,ierness,iernesses,ierment,ierments,"
+	      +"ierless,ierful,ierer,ierers,ierest",
+	      this),
+	    // 	(e.g., acidifier, tier)
+
+	    r(".aeiouy l + l e r",
+	      "&,&s,&est,&ed,&ing,&ings,ly,lely,&ness,&nesses,&ment,&ments,&ful,"
+	      +"&ers,&ered,&ering,&erings,&erly,&erness,&ernesses,&erments,"
+	      +"&erless,&erful",
+	      this),
+	    // 	(e.g., puller, filler, fuller)
+	    //  did not add: &erer, &erest, &errer, &errers, &errest,
+	    //  since i think the &er here is always an ending (?)
+
+	    r(".aeiouy s + s e r",
+	      "&,&es,&est,&ed,&ing,&ings,&ly,&ness,&nesses,&ment,&ments,&less,&ful,"
+	      +"&ers,&ered,&ering,&erings,&erly,&erness,&ernesses,&erment,&erments,"
+	      +"&erless,&erful",
+	      this),
+	    // 	(e.g., hisser, grosser)
+	    //  did not add: &erer, &erest, &errer, &errers, &errest,
+	    //  since i think the &er here is always an ending (?)
+
+	    r("bcdfghjklmnpqrstvwxyz aeiouy bdgkmnprt + & e r",
+	      "_,s,&est,&ed,&ing,&ings,ly,ness,nesses,ment,ments,less,ful,&ers,&ered,"
+	      +"&ering,&erings,&erly,&erness,&ernesses,&erments,&erless,&erful",
+	      this),
+	    // 	(e.g., bigger, trekker, hitter)
+	    //  did not add: &erer, &erest, &errer, &errers, &errest,
+	    //  since i think the &er here is always an ending (?)
+
+	    r(".aeiouy bcdfghjklmnpqrstvwxz + i z e r",
+	      "izes,ize,izers,ized,izing,izings,ization,izations,"
+	      +"ise,ises,iser,isers,ised,ising,isings,isation,isations",
+	      this),
+	    // 	(e.g., tokenize) // adds British variations
+
+	    r(".aeiouy bcdfghjklmnpqrstvwxz + i s e r",
+	      "ize,izes,izer,izers,ized,izing,izings,ization,izations,"
+	      +"ises,ise,isers,ised,ising,isings,isation,isations",
+	      this),
+	    // 	(e.g., tokenise) // British variant  // ~expertise
+
+	    r(".aeiouy + e r",
+	      "_,e,s,es,est,ed,ing,ings,ly,ely,ness,eness,nesses,enesses,ment,ments,"
+	      +"less,ful,ement,ements,eless,eful,ers,ered,erred,ering,erring,erings,"
+	      +"errings,erly,erness,ernesses,erment,erments,erless,erful,erer,erers,"
+	      +"erest,errer,errers,errest",
+	      this),
+	    // 	(e.g., actioner, atoner, icer, trader, accruer, churchgoer, prefer)
+	};
+
+	// For words ending in -est (est-rules):
+
+	Rule[] estRules = {
+	    r("bcdfghjklmnpqrstvwxyz + i e s t",
+	      "y,ies,ier,iers,ied,ying,yings,ily,yly,iness,yness,inesses,ynesses,"
+	      +"iment,iments,iless,iful",
+	      this),
+	    // 	(e.g., sliest, happiest, wittiest)
+
+	    r(".aeiouy l + l e s t",
+	      "&,&s,&er,&ers,&ed,&ing,&ings,ly,&ness,&nesses,&ment,&ments,&ful",
+	      this),
+	    // 	(e.g., fullest)
+
+	    r(".aeiouy s + s e s t",
+	      "&,&es,&er,&ers,&ed,&ing,&ings,&ly,&ness,&nesses,&ment,&ments,&less,&ful",
+	      this),
+	    // 	(e.g.,  grossest)
+
+	    r("bcdfghjklmnpqrstvwxyz aeiouy bdglmnprst + & e s t",
+	      "_,s,&er,&ers,&ed,&ing,&ings,ly,ness,nesses,ment,ments,less,ful",
+	      this),
+	    // 	(e.g., biggest)
+
+	    r(".aeiouy c h + e s t",
+	      "e,es,er,ers,ed,ing,ings,ly,ely,ness,eness,nesses,enesses,ment,ments,"
+	      +"less,ful,ement,ements,eless,eful,ests,ester,esters,ested,"
+	      +"esting,estings,estly,estness,estnesses,estment,estments,estless,estful",
+	      this),
+
+	    r(".aeiouy s h + e s t",
+	      "e,es,er,ers,ed,ing,ings,ly,ely,ness,eness,nesses,enesses,ment,ments,"
+	      +"less,ful,ement,ements,eless,eful,ests,ester,esters,ested,"
+	      +"esting,estings,estly,estness,estnesses,estment,estments,estless,estful",
+	      this),
+
+	    r(".aeiouy jxsz + e s t",
+	      "e,es,er,ers,ed,ing,ings,ly,ely,ness,eness,nesses,enesses,ment,ments,"
+	      +"less,ful,ement,ements,eless,eful,ests,ester,esters,ested,"
+	      +"esting,estings,estly,estness,estnesses,estment,estments,estless,estful",
+	      this),
+	    // 	(e.g., basest, archest, rashest)
+
+	    r("e r + e s t",
+	      "e,es,er,ers,ed,eing,eings,ely,eness,enesses,ement,ements,eless,eful,"
+	      +"ests,ester,esters,ested,esting,estings,estly,estness,estnesses,"
+	      +"estment,estments,estless,estful",
+	      this),
+	    // 	(e.g., severest, Xinterest, merest)
+
+	    r(".aeiouy + e s t",
+	      "_,e,s,es,er,ers,ed,ing,ings,ly,ely,ness,eness,nesses,enesses,ment,ments,"
+	      +"less,ful,ement,ements,eless,eful,ests,ester,esters,ested,esting,estings,"
+	      +"estly,estness,estnesses,estment,estments,estless,estful",
+	      this),
+	    // 	(e.g., slickest, coolest, ablest, amplest, protest, quest)
+	    //  polysyllables - note that this picks up quest because of the
+	    //  u but the forms generated are harmless
+
+	    r("e s t +",
+	      "s,er,ers,ed,ing,ings,ly,ness,nesses,ment,ments,less,ful",
+	      this),
+	    // 	(e.g., rest, test)
+	    //  monosyllables
+	};
+  
+	// For words ending in -ful (ful-rules ):
+
+	Rule[] fulRules = {
+	    r(".aeiouy bcdfghjklmnpqrstvwxyz + i f u l",
+	      "ifully,ifulness,*y",
+	      this),
+	    // 	(e.g., beautiful, plentiful)
+
+	    r(".aeiouy + f u l",
+	      "fully,fulness,*_",
+	      this),
+	    // 	(e.g., hopeful, sorrowful)
+	};
+  
+	// For words ending in -ical:
+
+	Rule[] icalRules = {
+	    r(".aeiouy + i c a l",
+	      "ic,ics,ically",
+	      this),
+	    // 	(e.g., academical, electrical, theatrical)
+	};
+
+	// For words ending in -ic:
+
+	Rule[] icRules = {
+	    r(".aeiouy + i c",
+	      "ics,ical,ically",
+	      this),
+	    // 	(e.g., academic, clinic, mechanic, methodic)
+	    //  we're now booting on all redos (w/ or w/out e) as too risky
+	};
+  
+	// For words ending in -ing (ing-rules):
+
+	Rule[] ingRules = {
+	    r("bcdfghjklmnpqrstvwxyz + y i n g",
+	      "yings,ie,y,ies,ier,iers,iest,ied,iely,yly,ieness,yness,ienesses,ynesses,"
+	      +"iment,iments,iless,iful",
+	      this),
+	    // 	(e.g., dying, crying, supplying)
+	    //  did not add -ing forms (see last 8 ing-rules)
+
+	    r(".aeiouy l + l i n g",
+	      "*_,&,&s,&er,&ers,&est,&ed,&ings,&ness,&nesses,&ment,&ments,&ful",
+	      this),
+	    // 	(e.g., pulling, filling, fulling)
+	    //  did not add -ing forms (see last 8 ing-rules)
+	    //  note that -ly has been dropped from this rule, as i believe
+	    //  that only a verb can be the stem here
+
+	    r(".aeiouy s + s i n g",
+	      "&,&s,&er,&ers,&est,&ed,&ings,&ly,&ness,&nesses,&ment,&ments,&less,&ful",
+	      this),
+	    // 	(e.g., hissing, grossing, processing)
+	    //  did not add -ing forms (see last 8 ing-rules)
+
+	    r("bcdfghjklmnpqrstvwxyz aeiouy bdgklmnprt + & i n g",
+	      "_,s,&er,&ers,&est,&ed,&ings,ly,ness,nesses,ment,ments,less,ful",
+	      this),
+	    // 	(e.g., hugging, trekking)
+	    //  did not add -ing forms (see last 8 ing-rules)
+
+	    r("+ e e i n g",
+	      "ee,ees,eer,eers,eest,eed,eeings,eely,eeness,eenesses,eement,eements,"
+	      +"eeless,eeful",
+	      this),
+	    // 	(e.g., freeing, agreeing)
+	    //  did not add -ing forms (see last 8 ing-rules)
+
+	    r("+ e i n g",
+	      "e,es,er,ers,est,ed,eings,ely,eness,enesses,ement,ements,eless,eful",
+	      this),
+	    // 	(e.g., ageing, aweing)
+	    //  did not add -ing forms (see last 8 ing-rules)
+
+	    r("aeiou y + i n g",
+	      "_,s,er,ers,est,ed,ings,ly,ingly,ness,nesses,ment,ments,less,ful",
+	      this),
+	    // 	(e.g., toying, playing)
+	    //  did not add -ing forms (see last 8 ing-rules)
+
+	    r(".aeiou bcdfghjklmnpqrstvwxyz eio t + i n g",
+	      "*_,*e,ings,inger,ingers,ingest,inged,inging,ingings,ingly,"
+	      +"ingness,ingnesses,ingment,ingments,ingless,ingful",
+	      this),
+	    //  (e.g., editing, crediting, expediting, siting, exciting
+	    //  deleting, completing, coveting, interpreting
+	    //  piloting, pivoting, devoting)
+
+	    r("bcdfghjklmnpqrstvwxyz aeiouy bdgklmt + i n g",
+	      "*e,ings,inger,ingers,ingest,inged,inging,ingings,ingly,"
+	      +"ingness,ingnesses,ingment,ingments,ingless,ingful",
+	      this),
+	    // 	(e.g., robing, siding, doling, translating, flaking)
+	    //  these consonants would double if there were no e in the stem
+	    //  removed p from this group: developing, galloping, etc.
+	    //  removed r from this group: monitoring, coloring, motoring
+	    //  removed n from this group: happening
+
+	    r(".aeiouy bcdfghjklmnpqrstvwxz + i z i n g",
+	      "izes,izer,izers,ized,ize,izings,ization,izations,"
+	      +"ise,ises,iser,isers,ised,ising,isings,isation,isations",
+	      this),
+	    // 	(e.g., tokenize) // adds British variations
+
+	    r(".aeiouy bcdfghjklmnpqrstvwxz + i s i n g",
+	      "ize,izes,izer,izers,ized,izing,izings,ization,izations,"
+	      +"ises,iser,isers,ised,ise,isings,isation,isations",
+	      this),
+	    // 	(e.g., tokenise) // British variant  // ~expertise
+
+	    r("aeiouy cgsvz + i n g",
+	      "*e,ings,inger,ingers,ingest,inged,inging,ingings,ingly,"
+	      +"ingness,ingnesses,ingment,ingments,ingless,ingful",
+	      this),
+	    // 	(e.g., icing, aging, achieving, amazing, housing)
+	    //  we had k in this list, but that's only right if the vowel
+	    //  is single - looking needs to be redone with _
+
+	    r("bcdfghjklmnpqrstvwxyz clsuv + i n g",
+	      "*e,ings,inger,ingers,ingest,inged,inging,ingings,ingly,"
+	      +"ingness,ingnesses,ingment,ingments,ingless,ingful",
+	      this),
+	    // 	(e.g., dancing, troubling, arguing, bluing, carving)
+
+	    r("lr g + i n g",
+	      "*e,ings,inger,ingers,ingest,inged,inging,ingings,ingly,"
+	      +"ingness,ingnesses,ingment,ingments,ingless,ingful",
+	      this),
+	    // 	(e.g., charging, bulging)
+
+	    r(".aeiouy bcdfghjklmnpqrstvwxyz bdfjkmnpqrtwxz + i n g",
+	      "*_,ings,inger,ingers,ingest,inged,inging,ingings,ingly,"
+	      +"ingness,ingnesses,ingment,ingments,ingless,ingful",
+	      this),
+	    // 	(e.g., farming, harping, interesting, bedspring, redwing)
+
+	    r(".aeiouy + i n g",
+	      "*_,*e,ings,inger,ingers,ingest,inged,inging,ingings,ingly,"
+	      +"ingness,ingnesses,ingment,ingments,ingless,ingful",
+	      this),
+	    // (e.g., spoiling, reviling, autoing, egging, hanging, hingeing,
+	    // judging, breathing, mothing)
+	    // these are the cases where we can't tell if e is needed or not
+
+	    r("+ i n g",
+	      "ings,inger,ingers,ingest,inged,inging,ingings,ingly,"
+	      +"ingness,ingnesses,ingment,ingments,ingless,ingful",
+	      this),
+	    // 	(e.g., wing, thing)
+	    //  monosyllables
+	};
+  
+	// For words ending in -leaf (leaf-rules):
+
+	Rule[] leafRules = {
+	    r("+ l e a f",
+	      "leaves",
+	      this),
+	    // 	(e.g., cloverleaf, flyleaf)
+	    //  leaf itself is in the exceptions list
+	};
+
+	// For words ending in -man:
+
+	Rule[] manRules = {
+	    r("+ m a n",
+	      "men,mans,maner,manner,manners,maners,manest,maned,manned,maning,"
+	      +"manning,manings,mannings,manly,manness,mannesses,manless,manful",
+	      this),
+	    // 	(e.g., woman, policeman, cayman, unman)
+	};
+
+	// For words ending in -men:
+
+	Rule[] menRules = {
+	    r("+ m e n",
+	      "man,mens,mener,meners,menest,mened,mening,menings,menly,"
+	      +"menness,mennesses,menless,menful",
+	      this),
+	    // 	(e.g., policewomen, hatchetmen, dolmen)
+	};
+  
+	// For words ending in -ment (ment-rules):
+
+	Rule[] mentRules = {
+	    r("s e g m e n t +",
+	      "s,ed,ing,ings,er,ers,ly,ness,nesses,less,ful",
+	      this),
+	    // 	(e.g., segment, bisegment, cosegment)
+
+	    r("p i g m e n t +",
+	      "s,ed,ing,ings,er,ers,ly,ness,nesses,less,ful",
+	      this),
+	    // 	(e.g., pigment, depigment, repigment)
+
+	    r(".aeiouy d g + m e n t",
+	      "*e",
+	      this),
+	    // 	(e.g., judgment, abridgment)
+
+	    r(".aeiouy bcdfghjklmnpqrstvwxyz + i m e n t",
+	      "*y",
+	      this),
+	    // 	(e.g., merriment, embodiment)
+
+	    r(".aeiouy + m e n t",
+	      "*_",
+	      this),
+	    // 	(e.g., atonement, entrapment)
+	};
+  
+	// For words ending in -o (o-rules):
+
+	Rule[] oRules = {
+	    r("aeiou o +",
+	      "s,er,ers,est,ed,ing,ings,ly,ness,nesses,ment,ments,less,ful",
+	      this),
+	    // 	(e.g., taboo, rodeo)
+	    //  no need to generate an es form
+
+	    r(".aeiouy o +",
+	      "s,es,er,ers,est,ed,ing,ings,ly,ness,nesses,ment,ments,less,ful",
+	      this),
+	    // 	(e.g., tomato, bonito)
+	    //  make both s and es plurals
+	};
+  
+	// For words ending in -um (um-rules):
+
+	Rule[] umRules = {
+	    r("+ u m",
+	      "a,ums,umer,ummer,umers,ummers,umed,ummed,uming,umming,umings,"
+	      +"ummings,umness,umments,umless,umful",
+	      this),
+	    // 	(e.g., datum, quantum, tedium, strum, [oil]drum, vacuum)
+	};
+
+	// For words ending in -y (y-rules):
+
+	Rule[] yRules = {
+	    r(".aeiouy b + l y",
+	      "le,les,ler,lers,lest,led,ling,lings,leness,lenesses,lement,lements,"
+	      +"leless,leful",
+	      this),
+	    // 	(e.g., ably, horribly, wobbly)
+
+	    r(".aeiouy bcdfghjklmnpqrstvwxyz + i l y",
+	      "y,ies,ier,iers,iest,ied,ying,yings,yness,iness,ynesses,inesses,"
+	      +"iment,iments,iless,iful",
+	      this),
+	    // 	(e.g., happily, dizzily)
+
+	    r(".aeiouy f u l + l y",
+	      "*_",
+	      this),
+	    // 	(e.g., peaceful+ly)
+
+	    r(".aeiouy l + l y",
+	      "*_,lies,lier,liers,liest,lied,lying,lyings,liness,linesses,"
+	      +"liment,liments,liless,liful,*l",
+	      this),
+	    // 	(e.g., fully, folly, coolly, fatally, dally)
+	    //  both -l and -ll words
+
+	    r("aou + l y",
+	      "lies,lier,liers,liest,lied,lying,lyings,liness,linesses,"
+	      +"liment,liments,liless,liful",
+	      this),
+	    // 	(e.g., monopoly, Xcephaly, holy)
+	    //  i.e., treat ly as part of the stem
+
+	    r("+ l y",
+	      "*_,lies,lier,liers,liest,lied,lying,lyings,liness,linesses,lyless,lyful",
+	      this),
+	    // 	(e.g., frequently, comely, deeply, apply, badly)
+	    //  i.e., redo stem AND generate all forms with ly as part of stem
+
+	    r("bcdfghjklmnpqrstvwxyz + y",
+	      "ies,ier,iers,iest,ied,ying,yings,ily,yness,iness,ynesses,inesses,"
+	      +"iment,iments,iless,iful,yment,yments,yless,yful",
+	      this),
+	    // 	(e.g., happy, spy, cry)
+
+	    r("aeiou y +",
+	      "s,er,ers,est,ed,ing,ings,ly,ness,nesses,ment,ments,less,ful",
+	      this),
+	    // 	(e.g., betray, gay, stay)
+	};
+
+	// For other words (root-rules):
+  
+	Rule[] rootRules = {
+	    r(".aeiouy c h +",
+	      "es,er,ers,est,ed,ing,ings,ly,ness,nesses,ment,ments,less,ful",
+	      this),
+
+	    r(".aeiouy s h +",
+	      "es,er,ers,est,ed,ing,ings,ly,ness,nesses,ment,ments,less,ful",
+	      this),
+
+	    r(".aeiouy jxz +",
+	      "es,er,ers,est,ed,ing,ings,ly,ness,nesses,ment,ments,less,ful",
+	      this),
+	    // 	(e.g., fix, arch, rash)
+
+	    r(".aeiouy bcdfghjklmnpqrstvwxyz aeiouy bdglmnprt +",
+	      "s,er,ers,est,ed,ing,ings,&er,&ers,&est,&ed,&ing,&ings,ly,"
+	      +"ness,nesses,ment,ments,less,ful",
+	      this),
+	    // 	(e.g., unflag, open, besot)
+	    //  both possibilities for multisyllables
+
+	    r("bcdfghjklmnpqrstvwxyz aeiouy bdglmnprt +",
+	      "s,&er,&ers,&est,&ed,&ing,&ings,ly,ness,nesses,ment,ments,less,ful",
+	      this),
+	    // 	(e.g., bed, cop)
+
+	    r(".aeiouy bcdfghjklmnpqrstvwxyz aeiouy m a + t a",
+	      "_, s,tas,tum,tums,ton,tons,tic,tical",
+	      this),
+	    // 	(e.g., schemata, automata)
+
+	    r(".aeiouy t + a",
+	      "as,ae,um,ums,on,ons,ic,ical",
+	      this),
+	    // 	(e.g., chordata, data, errata, sonata, toccata)
+
+	    r(".aeiouy .bcdfghjklmnpqrstvwxyz + a",
+	      "as,ae,ata,um,ums,on,ons,al,atic,atical",
+	      this),
+	    // 	(e.g., schema, ova, polyhedra)
+
+	    r(".aeiouy l l +",
+	      "s,er,ers,est,ed,ing,ings,y,ness,nesses,ment,ments,-less,ful",
+	      this),
+	    // 	(e.g., full)
+	    //  note: adds a hyphen before less
+
+	    r(".aeiouy +",
+	      "s,er,ers,est,ed,ing,ings,ly,ness,nesses,ment,ments,less,ful",
+	      this),
+	    // 	(e.g., spoon, rhythm)
+	};
+
+	rulesTable = new Hashtable();
+	rulesTable.put("s", sRules);
+	rulesTable.put("e", eRules);
+	rulesTable.put("ed", edRules);
+	rulesTable.put("er", erRules);
+	rulesTable.put("est", estRules);
+	rulesTable.put("ful", fulRules);
+	rulesTable.put("ic", icRules);
+	rulesTable.put("ical", icalRules);
+	rulesTable.put("ing", ingRules);
+	rulesTable.put("man", manRules);
+	rulesTable.put("men", menRules);
+	rulesTable.put("ment", mentRules);
+	rulesTable.put("leaf", leafRules);
+	rulesTable.put("o", oRules);
+	rulesTable.put("um", umRules);
+	rulesTable.put("y", yRules);
+	rulesTable.put("default", rootRules);
+    }
+
+  
+}
diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/Location.java b/jhMaster/JSearch/client/com/sun/java/help/search/Location.java
new file mode 100644
index 0000000000000000000000000000000000000000..701d0ad44e816195f579d03325e6a57a3c175b23
--- /dev/null
+++ b/jhMaster/JSearch/client/com/sun/java/help/search/Location.java
@@ -0,0 +1,60 @@
+/*
+ * @(#)Location.java	1.6 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @date   1/13/98
+ * @author Jacek R. Ambroziak
+ * @group  Sun Microsystems Laboratories
+ */
+
+package com.sun.java.help.search;
+
+class Location
+{
+  private final int _docID;
+  private final int _begin;
+  private final int _end;
+  
+  public Location(int doc, int begin, int end)
+  {
+    _docID = doc;
+    _begin = begin;
+    _end = end;
+  }
+  
+  public int getDocument() {
+    return _docID;
+  }
+
+  public int getBegin() {
+    return _begin;
+  }
+
+  public int getEnd() {
+    return _end;
+  }
+}
diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/MemoryRAFFile.java b/jhMaster/JSearch/client/com/sun/java/help/search/MemoryRAFFile.java
new file mode 100644
index 0000000000000000000000000000000000000000..6c66ad7f11611e52894efe6eb3ec8ca449119e78
--- /dev/null
+++ b/jhMaster/JSearch/client/com/sun/java/help/search/MemoryRAFFile.java
@@ -0,0 +1,158 @@
+/*
+ * @(#)MemoryRAFFile.java	1.12 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @(#) MemoryRAFFile.java 1.12 - last change made 10/30/06
+ */
+
+package com.sun.java.help.search;
+
+/**
+ * A DICT (Dictionary) file cached in memory.
+ *
+ * @author Roger D. Brinkley
+ * @version	1.12	10/30/06
+ */
+
+import java.net.URL;
+import java.net.URLConnection;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.BufferedInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.EOFException;
+
+public class MemoryRAFFile extends RAFFile {
+
+    private URL url;
+    private byte[] data;
+    private int size;
+    private int filePointer;
+
+    public MemoryRAFFile(URLConnection connection) throws IOException {
+	this.url = connection.getURL();
+
+	InputStream in = new BufferedInputStream(connection.getInputStream());
+	ByteArrayOutputStream data = new ByteArrayOutputStream();
+
+	byte[] buf = new byte[512];
+	int i = 0;
+	while((i = in.read(buf)) != -1) {
+	    data.write(buf, 0, i);
+	}
+	this.data = data.toByteArray();
+	size = data.size();
+	filePointer = 0;
+    }
+
+    public long length() { 
+	return size;
+    }
+
+    public void close() throws IOException {
+	filePointer = 0;
+	data = null;
+	size = 0;
+    }
+
+    public long getFilePointer() throws IOException {
+	return filePointer;
+    }
+
+    public void seek(long pos) throws IOException {
+	if (pos > size) {
+	    throw new IOException();
+	}
+	filePointer = (int)pos;
+    }
+
+    public int read() throws IOException {
+	if (filePointer >= size) {
+	    return -1;
+	}
+	filePointer += 1;
+	return data[filePointer - 1] & 0xFF;
+    }
+
+    private int readBytes(byte b[], int off, int len) throws IOException {
+	debug ("readBytes");
+	if (filePointer + off + len > size) {
+	    throw new IOException();
+	}
+	filePointer += off;
+	System.arraycopy(data, filePointer, b, 0, (int)len);
+	filePointer += len;
+	return len;
+    }
+
+    public int read(byte b[], int off, int len) throws IOException {
+	return readBytes(b, off, len);
+    }
+
+    public int readInt() throws IOException {
+	debug ("readInt");
+	int ch1 = this.read();
+	int ch2 = this.read();
+	int ch3 = this.read();
+	int ch4 = this.read();
+	if ((ch1 | ch2 | ch3 | ch4) < 0)
+	    throw new EOFException();
+	return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0));
+    }
+
+    public final void readFully(byte b[]) throws IOException {
+	readFully(b, 0, b.length);
+    }
+
+    private void readFully (byte b[], int off, int len) 
+	throws IOException {
+        int n = 0;
+	do {
+	    int count = this.read(b, off + n, len - n);
+	    if (count < 0)
+		throw new EOFException();
+	    n += count;
+	} while (n < len);
+    }
+
+    public void writeInt(int v) throws IOException {
+	throw new IOException("Unsupported Operation");
+    }
+
+    public void write(byte b[]) throws IOException {
+	throw new IOException("Unsupported Operation");
+    }
+    /**
+     * For printf debugging.
+     */
+    private static boolean debugFlag = false;
+    private static void debug(String str) {
+        if( debugFlag ) {
+            System.out.println("MemoryRAFFile: " + str);
+        }
+    }
+}
diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/NextDocGenerator.java b/jhMaster/JSearch/client/com/sun/java/help/search/NextDocGenerator.java
new file mode 100644
index 0000000000000000000000000000000000000000..ca79beac31724c1ab4d5bbe0acccca7cc86c81ac
--- /dev/null
+++ b/jhMaster/JSearch/client/com/sun/java/help/search/NextDocGenerator.java
@@ -0,0 +1,90 @@
+/*
+ * @(#)NextDocGenerator.java	1.6 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @date   1/13/98
+ * @author Jacek R. Ambroziak
+ * @group  Sun Microsystems Laboratories
+ */
+
+package com.sun.java.help.search;
+
+class NextDocGenerator
+{
+  private int                   _document;
+  private final int              _concept;
+  private final int              _queryMask;
+  private final ConceptData      _terms;
+  private final NonnegativeIntegerGenerator  _iterator;
+
+  public NextDocGenerator(ConceptData cd, SearchEnvironment env)
+  {
+    _document = 0;
+    _concept = cd.getConcept();
+    _queryMask = cd.getQueryMask();
+    _terms = cd;
+    _iterator = env.getDocumentIterator(_concept);
+  }
+  
+  public int first() throws Exception {
+    return _document =
+      _iterator != null ? _iterator.first() : NonnegativeIntegerGenerator.END;
+  }
+  
+  public int next() throws Exception {
+    return _document = _iterator.next();
+  }
+  
+  public int getDocument() {
+    return _document;
+  }
+  
+  public int getConcept() {
+    return _concept;
+  }
+  
+  public ConceptData getTerms() {
+    return _terms;
+  }
+  
+  public int getQueryMask() {
+    return _queryMask;
+  }
+  
+  // for sorting
+  public boolean compareWith(NextDocGenerator other)
+  {
+    return _document > other._document  
+      || _document == other._document && _concept > other._concept;
+  }
+
+  public boolean smallerThan(NextDocGenerator other)
+  {
+    return _document < other._document  
+      || _document == other._document && _concept < other._concept;
+  }
+}
diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/NextDocGeneratorHeap.java b/jhMaster/JSearch/client/com/sun/java/help/search/NextDocGeneratorHeap.java
new file mode 100644
index 0000000000000000000000000000000000000000..fd4f157d401d0ef7efca1ca58dbd59032ef1541f
--- /dev/null
+++ b/jhMaster/JSearch/client/com/sun/java/help/search/NextDocGeneratorHeap.java
@@ -0,0 +1,127 @@
+/*
+ * @(#)NextDocGeneratorHeap.java	1.7 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @date   1/13/98
+ * @author Jacek R. Ambroziak
+ * @group  Sun Microsystems Laboratories
+ */
+
+package com.sun.java.help.search;
+
+class NextDocGeneratorHeap
+{
+  private static final int InitSize = 1024;
+  
+  private int                _heapSize = 0;
+  private int                _size = InitSize;
+  private NextDocGenerator[] _heap = new NextDocGenerator[InitSize];
+  private int                _free = 0;
+  private boolean             _nonEmpty = false;
+  
+  public boolean isNonEmpty() {
+    return _nonEmpty;
+  }
+  
+  public void addGenerator(NextDocGenerator gen)
+  {
+    if (_free == _size)
+      {
+	NextDocGenerator[] newArray = new NextDocGenerator[_size *= 2];
+	System.arraycopy(_heap, 0, newArray, 0, _free);
+	_heap = newArray;
+      }
+    _heap[_free++] = gen;
+  }
+  
+  public void start()
+  {
+    if ((_heapSize = _free) > 0)
+      {
+	// build heap
+	for (int i = _heapSize/2; i >= 0; i--)
+	  heapify(i);
+	_nonEmpty = true;
+      }
+    else
+      _nonEmpty = false;
+  }
+  
+  public void step() throws Exception
+  {
+    if (_heap[0].next() != NonnegativeIntegerGenerator.END)
+      heapify(0);
+    else if (_heapSize > 1)
+      {
+	_heap[0] = _heap[--_heapSize];
+	heapify(0);
+      }
+    else
+      _nonEmpty = false;
+  }
+  
+  public int getDocument() {
+    return _heap[0].getDocument();
+  }
+  
+  public int getConcept() {
+    return _heap[0].getConcept();
+  }
+  
+  public ConceptData getTerms() {
+    return _heap[0].getTerms();
+  }
+  
+  public int getQueryMask() {
+    return _heap[0].getQueryMask();
+  }
+  
+  public void reset()
+  {
+    _nonEmpty = false;
+    _free = 0;
+  }
+  
+  public boolean atDocument(int document) {
+    return _nonEmpty && _heap[0].getDocument() == document;
+  }
+  
+  private void heapify(int i)
+  {
+    int r = (i + 1) << 1, l = r - 1;
+    int smallest = l < _heapSize && _heap[l].smallerThan(_heap[i]) ? l : i;
+    if (r < _heapSize && _heap[r].smallerThan(_heap[smallest]))
+      smallest = r;
+    if (smallest != i)
+      {
+	NextDocGenerator temp = _heap[smallest];
+	_heap[smallest] = _heap[i];
+	_heap[i] = temp;
+	heapify(smallest);
+      }
+  }
+}
diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/NonnegativeIntegerGenerator.java b/jhMaster/JSearch/client/com/sun/java/help/search/NonnegativeIntegerGenerator.java
new file mode 100644
index 0000000000000000000000000000000000000000..76cdb9a7ac0244aadf3725728d4d77ea03a65b33
--- /dev/null
+++ b/jhMaster/JSearch/client/com/sun/java/help/search/NonnegativeIntegerGenerator.java
@@ -0,0 +1,42 @@
+/*
+ * @(#)NonnegativeIntegerGenerator.java	1.6 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @date   1/13/98
+ * @author Jacek R. Ambroziak
+ * @group  Sun Microsystems Laboratories
+ */
+
+package com.sun.java.help.search;
+
+interface NonnegativeIntegerGenerator
+{
+  int END = -1;
+
+  int first() throws Exception;
+  int next() throws Exception;
+}
diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/Query.java b/jhMaster/JSearch/client/com/sun/java/help/search/Query.java
new file mode 100644
index 0000000000000000000000000000000000000000..170eed32eac7ea245b78eefe5a911971fc59a5c3
--- /dev/null
+++ b/jhMaster/JSearch/client/com/sun/java/help/search/Query.java
@@ -0,0 +1,177 @@
+/*
+ * @(#)Query.java	1.12 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @date   1/13/98
+ * @author Jacek R. Ambroziak
+ * @group  Sun Microsystems Laboratories
+ */
+
+package com.sun.java.help.search;
+
+import java.util.*;
+import javax.help.search.SearchQuery;
+import javax.help.search.SearchItem;
+
+class Query
+{
+
+  private double  _currentStandard;
+  private final int _nColumns;
+  private double[] _missingPenalty;
+  private double[] _upperboundTemplate;
+  private double[] _penalties;
+  
+  private final SearchEnvironment _env;
+  private int                 _hitCounter;
+  private boolean                 _vote;
+  
+  private HitStore  _store;
+  
+  public Query(SearchEnvironment env, int nColumns, double[] missingPenalties)
+  {
+    _env = env;
+    _nColumns = nColumns;
+    _missingPenalty = new double[nColumns];
+    _upperboundTemplate = new double[nColumns];
+    _penalties = missingPenalties;
+    _hitCounter = 0;
+    _vote = false;
+    _currentStandard = (nColumns - 1) * 10.0 + 9.9999;
+    _store = new HitStore(_currentStandard);
+    for (int i = 0; i < _nColumns; i++)
+      _missingPenalty[i] = missingPenalties != null
+	? missingPenalties[i]
+	: 10.0;
+    makePenaltiesTable();
+  }
+
+  public void makeEvent(int n, SearchQuery searchQuery)
+    {
+	Vector hits = new Vector(n);
+
+    if (n > 0)
+      {
+	int N = n;
+	QueryHit qh = _store.firstBestQueryHit();
+	n = N;
+	for ( ; qh != null; qh = --n > 0 ? _store.nextBestQueryHit() : null)
+	  try {
+	    hits.addElement(_env.makeItem(qh));
+	  }
+	catch (Exception e) {
+	  System.err.println(e + "hit not translated");
+	}
+      }
+    // Params not know at this time
+    searchQuery.itemsFound(true, hits);
+    }
+
+  public double lookupPenalty(int pattern) {
+    return _penalties[pattern];
+  }
+  
+  public double getOutOufOrderPenalty() {
+    return 0.25;
+  }
+  
+  public double getGapPenalty() {
+    return 0.005;
+  }
+  
+  public int getNColumns() {
+    return _nColumns;
+  }
+  
+  public boolean goodEnough(double penalty) {
+    return penalty <= _currentStandard;
+  }
+  
+  public int[] getConceptArrayOfNewHit(double penalty, Location loc)
+  {
+    QueryHit hit = new QueryHit(loc, penalty, _nColumns);
+    _store.addQueryHit(hit);
+    _hitCounter++;
+    return hit.getArray();
+  }
+
+  public void resetForNextDocument()
+  {
+    _currentStandard = _store.getCurrentStandard();
+    // "everything's missing"
+    for (int i = 0; i < _nColumns; i++)
+      _upperboundTemplate[i] = _missingPenalty[i];
+    _vote = false;
+  }
+
+  public boolean vote()
+  {
+    double sum = 0.0;
+    for (int i = 0; i < _nColumns; i++)
+      sum += _upperboundTemplate[i];
+    return _vote = (sum <= _currentStandard);
+  }
+
+  public void updateEstimate(int role, double penalty) {
+    if (penalty < _upperboundTemplate[role])
+      _upperboundTemplate[role] = penalty;
+  }
+  
+  public void printHits(int n)
+  {
+    if (n > 0)
+      {
+	int N = n;
+	QueryHit qh = _store.firstBestQueryHit();
+	n = N;
+	for ( ; qh != null; qh = --n > 0 ? _store.nextBestQueryHit() : null)
+	  try {
+	    System.out.println(_env.hitToString(qh));
+	  }
+	catch (Exception e) {
+	  System.err.println(e + "hit not translated");
+	}
+      }
+  }
+
+  private void makePenaltiesTable()
+  {
+    int nPatterns = 1 << _nColumns;
+    _penalties = new double[nPatterns];
+    for (int i = 0; i < nPatterns; i++)
+      _penalties[i] = computePenalty(i);
+  }
+
+  private double computePenalty(int n)
+  {
+    double penalty = 0.0;
+    for (int i = 0; i < _nColumns; i++)
+      if ((n & 1 << i) == 0)
+	penalty += _missingPenalty[i];
+    return penalty;
+  }
+}
diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/QueryEngine.java b/jhMaster/JSearch/client/com/sun/java/help/search/QueryEngine.java
new file mode 100644
index 0000000000000000000000000000000000000000..a3b14a548d34bd5110b1de6b9d3c9dea5220da01
--- /dev/null
+++ b/jhMaster/JSearch/client/com/sun/java/help/search/QueryEngine.java
@@ -0,0 +1,235 @@
+/*
+ * @(#)QueryEngine.java	1.25 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @version	1.25	10/30/06
+ */
+
+package com.sun.java.help.search;
+
+import java.text.BreakIterator;
+import java.util.Vector;
+import java.util.Locale;
+import java.util.Enumeration;
+import java.lang.reflect.Method;
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.io.File;
+import java.net.URL;
+import javax.help.search.SearchQuery;
+import javax.help.HelpUtilities;
+
+/**
+ * This class is the initial interface into the search engine. It can be 
+ * run as a standalone search engine or instantiated as a class.
+ *
+ * @author Jacek R. Ambroziak
+ * @author Roger D. Brinkley
+ * @author Eduardo Pelegri-Llopart
+ * @version	1.25	10/30/06
+ */
+
+public class QueryEngine
+{
+    private SearchEnvironment _env;
+
+    public QueryEngine(String indexDir, URL hsBase) throws Exception {
+	_env = new SearchEnvironment(indexDir, hsBase);
+    }
+
+    public void processQuery(String query, Locale l, SearchQuery searchQuery) throws Exception
+    {
+	BreakIterator boundary;
+	int start;
+	String term;
+	Vector ids = new Vector();;
+	LiteMorph morph = getMorphForLocale(l);
+	int col=-1;
+
+	try {
+	    boundary = BreakIterator.getWordInstance(l);
+	    boundary.setText(query);
+	    start = boundary.first();
+	    for (int end = boundary.next();
+		 end != BreakIterator.DONE;
+		 start = end, end = boundary.next()) {
+		term = new String(query.substring(start,end));
+		term = term.trim();
+		term = term.toLowerCase(l);
+		if (term.length() > 1) {
+		    col += 1;
+		    int id = _env.fetch(term);
+		    if (id > 0) {
+			ids.addElement(new SearchIds(col, id, 0.0));
+		    }
+		    if (morph != null) {
+			String [] morphs = morph.variantsOf(term);
+			for (int i=0; i < morphs.length ; i++) {
+			    int id2 = _env.fetch(morphs[i]);
+			    if (id2 > 0) {
+				ids.addElement(new SearchIds(col, id2, 0.1));
+			    }
+			}
+		    }
+		} else if (term.length() == 1) {
+		    int charType = Character.getType(term.charAt(0));
+		    if ((charType == Character.DECIMAL_DIGIT_NUMBER) || 
+			(charType == Character.LETTER_NUMBER) || 
+			(charType == Character.LOWERCASE_LETTER) || 
+			(charType == Character.OTHER_LETTER) || 
+			(charType == Character.OTHER_NUMBER) || 
+			(charType == Character.TITLECASE_LETTER) || 
+			(charType == Character.UNASSIGNED) || 
+			(charType == Character.UPPERCASE_LETTER)) {
+			col += 1;
+			int id = _env.fetch(term);
+			if (id > 0) {
+			    ids.addElement(new SearchIds(col, id, 0.0));
+			}
+			if (morph != null) {
+			    String [] morphs = morph.variantsOf(term);
+			    for (int i=0; i < morphs.length ; i++) {
+				int id2 = _env.fetch(morphs[i]);
+				if (id2 > 0) {
+				    ids.addElement(new SearchIds(col, id2, 0.1));
+				}
+			    }
+			}
+		    }
+		}
+	    }
+	}
+	catch (Exception e) {
+	    e.printStackTrace();
+	}
+	int size = ids.size();
+	Search search = new Search(_env, col + 1);
+	IntegerArray children = new IntegerArray();
+
+	// add the terms and any children of a given term to the list of 
+	// searched items. Penalize the children slightly
+	for (int i = 0; i < size; i++)
+	    {
+		SearchIds id = (SearchIds) ids.elementAt(i);
+		search.addTerm(id.col, id.concept, id.score, 0);
+		children.clear();
+		_env.getChildren(id.concept, children);
+		if (children.cardinality() > 0)
+		    for (int j = 0; j < children.cardinality(); j++)
+			{
+			    search.addTerm(id.col, children.at(j), 
+					   id.score + 0.1, 0);
+			    // appending (grand)+children
+			    //!!! as it is too many duplicates are added
+			    _env.getChildren(children.at(j), children);
+			}
+	    }
+
+	search.startSearch(searchQuery);
+    }
+
+    private LiteMorph getMorphForLocale(Locale l) {
+	// In the event that nolocale has been defined try English
+	if (l == null) {
+	    l = Locale.ENGLISH;
+	}
+	//Try to find a locale version of LiteMorph
+	Enumeration enum1 = HelpUtilities.getCandidates(l);
+	String front = "com.sun.java.help.search.LiteMorph";
+	ClassLoader cl = QueryEngine.class.getClassLoader();
+	while (enum1.hasMoreElements()) {
+	    String tail = (String) enum1.nextElement();
+	    String name = new String(front + tail);
+	    try {
+		Class klass;
+		if (cl == null) {
+		    klass = Class.forName(name);
+		} else {
+		    klass = cl.loadClass(name);
+		}
+		Method method = klass.getMethod ("getMorph", 
+						 (java.lang.Class[]) null);
+		return (LiteMorph) method.invoke(null, 
+						 (java.lang.Object[]) null);
+	    } catch (Exception e) {
+		continue;
+	    }
+	}
+	// couldn't find a match 
+	return null;
+    }
+
+
+    public static void main(String[] args)
+    {
+	try {
+	    // BufferedReader is needed for readLine() method
+	    BufferedReader in =
+		// but we'll make it a degenerate buffer of 1
+		// to workaround a problem with some PC implementation
+		// which wouldn't start to read before a lot of chars
+		// were typed
+		new BufferedReader(new InputStreamReader(System.in), 1);
+	    String file = new String (args[0]);
+	    QueryEngine qe = new QueryEngine(file, null);
+	    System.out.println("initialized; enter query");
+	    while(true)
+		{
+		    String line = in.readLine();
+		    if (line.equals("."))
+			break;
+		    else
+		      {
+			long start = System.currentTimeMillis();
+			qe.processQuery(line, Locale.getDefault(), null);
+			System.out.println((System.currentTimeMillis()-start)
+					   +" msec search");
+		      }
+		    System.out.println("enter next query or . to quit");
+		}
+	}
+	catch (Exception e) {
+	    e.printStackTrace();
+	}
+    }
+
+    private class SearchIds {
+	public int col;
+	public int concept;
+	public double score;
+
+	public SearchIds (int col, int concept, double score) {
+	    this.col = col;
+	    this.concept = concept;
+	    this.score = score;
+	}
+
+	public String toString() {
+	    return "col=" + col + " concept=" + concept + " score=" + score;
+	}
+    }
+}
diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/QueryHit.java b/jhMaster/JSearch/client/com/sun/java/help/search/QueryHit.java
new file mode 100644
index 0000000000000000000000000000000000000000..b99a27b7ef32d440f810efc262fdfa43d6684fae
--- /dev/null
+++ b/jhMaster/JSearch/client/com/sun/java/help/search/QueryHit.java
@@ -0,0 +1,87 @@
+/*
+ * @(#)QueryHit.java	1.6 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @date   1/13/98
+ * @author Jacek R. Ambroziak
+ * @group  Sun Microsystems Laboratories
+ */
+
+package com.sun.java.help.search;
+
+class QueryHit
+{
+  private int _doc;
+  private int _begin;
+  private int _end;
+  private double _score;
+  private final int[] _concepts;
+
+  public QueryHit(Location loc, double penalty, int nColumns)
+  {
+    _score = penalty;
+    _doc = loc.getDocument();
+    _begin = loc.getBegin();
+    _end = loc.getEnd();
+    _concepts = new int[nColumns];
+  }
+  
+  public String toString() {
+    return "[doc = "+_doc+", "+_begin+", "+_end+", "+_score+"]";
+  }
+
+  public int getDocument() {
+    return _doc;
+  }
+
+  public int getBegin() {
+    return _begin;
+  }
+
+  public int getEnd() {
+    return _end;
+  }
+
+  public double getScore() {
+    return _score;
+  }
+
+  public int[] getArray() {
+    return _concepts;
+  }
+
+  public boolean betterThan(QueryHit x)
+  {
+    if (_score < x._score) return true;
+    if (_score > x._score) return false;
+    if (_begin < x._begin) return true;
+    if (_begin > x._begin) return false;
+    if (_end < x._end) return true;
+    if (_end > x._end) return false;
+    return false;
+  }
+}
diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/RAFFile.java b/jhMaster/JSearch/client/com/sun/java/help/search/RAFFile.java
new file mode 100644
index 0000000000000000000000000000000000000000..cd066537727c887e7185ad29fec7c20d15569c2c
--- /dev/null
+++ b/jhMaster/JSearch/client/com/sun/java/help/search/RAFFile.java
@@ -0,0 +1,116 @@
+/*
+ * @(#)RAFFile.java	1.14 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @(#) RAFFile.java 1.14 - last change made 10/30/06
+ */
+
+package com.sun.java.help.search;
+
+import java.io.IOException;
+
+/**
+ * This class can be used to read/write the contents of a RAF type files
+ * (i.e. DICT (Dictionary) & POSITIONS (Positions))
+ * file as part of JavaHelp Search Database. It uses RandamAccessFile for 
+ * quick access to dictionary blocks (DictBlock). 
+ * </p>
+ * Extension of this class serve include memory resident  or unwriteable  
+ * RAFFile.
+ *
+ * @author Roger D. Brinkley
+ * @author Eduardo Pelegri-Llopart
+ * @version	1.14	10/30/06
+ */
+
+import java.net.URL;
+import java.io.RandomAccessFile;
+import java.io.File;
+import java.io.IOException;
+
+public class RAFFile {
+    private RandomAccessFile raf;
+
+    protected RAFFile() {
+    }
+
+    public RAFFile(String name, boolean update) throws IOException {
+	debug("RAFFile " + name);
+	raf = new RandomAccessFile(name, update?"rw":"r");
+    }
+
+    public long length() throws IOException { 
+	return raf.length();
+    }
+
+    public long getFilePointer() throws IOException {
+	return raf.getFilePointer();
+    }
+
+    public void close() throws IOException {
+	raf.close();
+    }
+
+    public void seek(long pos) throws IOException {
+	raf.seek(pos);
+    }
+
+    public int readInt() throws IOException {
+	return raf.readInt();
+    }
+
+    public int read() throws IOException {
+	return raf.read();
+    }
+
+    public void readFully (byte b[]) throws IOException {
+	raf.readFully(b);
+    }
+
+    public int read(byte[] b, int off, int len) throws IOException {
+	return raf.read(b, off, len);
+    }
+  
+    public void writeInt(int v) throws IOException {
+	raf.writeInt(v);
+    }
+
+    public void write(byte b[]) throws IOException {
+	raf.write(b);
+    }
+
+    /**
+     * Debug code
+     */
+
+    private static final boolean debug = false;
+    private static void debug(String msg) {
+        if (debug) {
+            System.err.println("RAFFile: "+msg);
+        }
+    }
+}
diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/RAFFileFactory.java b/jhMaster/JSearch/client/com/sun/java/help/search/RAFFileFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..1d80b0db99155d6dd94fab0d736caf73c17c255c
--- /dev/null
+++ b/jhMaster/JSearch/client/com/sun/java/help/search/RAFFileFactory.java
@@ -0,0 +1,171 @@
+/*
+ * @(#)RAFFileFactory.java	1.27 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @(#) RAFFileFactory.java 1.27 - last change made 10/30/06
+ */
+
+package com.sun.java.help.search;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+import java.lang.reflect.*;
+
+/**
+ * A factory for files that can be accessed as Random Access file from a URL. 
+ * RAFFiles can either be an acutall RAF file or a memory version of the
+ * RAF file. When a URL is it is opened as a RAF file, otherwise it is moved
+ * to a temporary file if possible or into a memory resident version.
+ * 
+ *
+ * @author Roger D. Brinkley
+ * @version	1.27	10/30/06
+ */
+class RAFFileFactory {
+
+    /**
+     * Cannot create these, need to go through the factory method
+     */
+    private RAFFileFactory() {
+    }
+
+    static RAFFileFactory theFactory;
+
+    public static synchronized RAFFileFactory create() {
+	if (theFactory == null) {
+	    theFactory = new RAFFileFactory();
+	}
+	return theFactory;
+    }
+
+    /* For this connection, when to cache in memory and when to disk */
+    private int memoryCacheLimit = 10000;
+
+    private boolean isFileURL(URL url) {
+	return url.getProtocol().equalsIgnoreCase("file");
+    }
+
+    public int getMemoryCacheLimit() {
+	return memoryCacheLimit;
+    }
+
+    public void setMemoryCacheLimit(int limit) {
+	this.memoryCacheLimit = limit;
+    }
+
+    public synchronized RAFFile get(URL url, boolean update) 
+	throws IOException {
+
+	RAFFile result = null;
+
+	if (isFileURL(url)) {
+	    try {
+		String f = url.getFile();
+
+		// Normalize the string. This is required because of a
+		// backwards incompatability change in JDK 1.4.0 and later
+		// releases.
+		f = Utilities.URLDecoder(f);
+
+		// refactor so it runs with verification on...
+
+		// Object o = new FilePermission(f, update ? "write":"read");
+		// here -- check if AccessController.checkPermission(p);
+
+		result =  new RAFFile(f, update);
+		debug ("Opened Dict file with file protocol:" +  f);
+	    } catch (SecurityException e) {
+		// cannot do "it" -- code is not yet in place
+	    }
+	}
+	if (result == null) {
+	    result = createLocalRAFFile(url);
+	}
+	if (result == null) {
+	    throw new FileNotFoundException(url.toString());
+	}
+	return result;
+    }
+
+
+    /** 
+     * Given a URL, retrieves a DICT file and creates a cached DICT
+     * file object. If the file is larger than the size limit,
+     * and if temp files are supported by the Java virtual machine,
+     * the DICT file is it is cached to disk. Otherwise the DICT file 
+     * is cached in memory.
+     */
+    private static RAFFile createLocalRAFFile(URL url) throws IOException {
+
+	RAFFile result = null;
+	URLConnection connection = url.openConnection();
+
+	// We should be able to just do a catch on missing method but
+	// IE4.0 does not like this
+	//
+	//	try {
+	//	    Object foo = connection.getPermission();
+	//
+	//	    result = RAFFileFactoryOn12.get(connection);
+	//
+	//	} catch (NoSuchMethodError ex) {
+	//	    // on 1.1 all we can do is create a memory file
+	//	    result = new MemoryRAFFile(connection);
+	//	    debug ("Opening a Dict file in Memory");
+	//	}
+	//
+
+	try {
+	    Class types[] = {};
+	    Method m = URLConnection.class.getMethod("getPermission", types);
+	    result = RAFFileFactoryOn12.get(connection);
+	} catch (NoSuchMethodError ex) {
+	    // as in JDK1.1
+	} catch (NoSuchMethodException ex) {
+	    // as in JDK1.1
+	}
+
+	if (result == null) {
+	    // on 1.1 all we can do is create a memory file
+	    result = new MemoryRAFFile(connection);
+	    debug ("Opening a Dict file in Memory");
+	}
+	return result;
+    }
+
+    /**
+     * Debug code
+     */
+
+    private static final boolean debug = false;
+    private static void debug(String msg) {
+        if (debug) {
+            System.err.println("RAFFileFactory: "+msg);
+        }
+    }
+}
diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/RAFFileFactoryOn12.java b/jhMaster/JSearch/client/com/sun/java/help/search/RAFFileFactoryOn12.java
new file mode 100644
index 0000000000000000000000000000000000000000..8d5fa55e0ab2919fb3a2ae6d7c17a7f27f67b163
--- /dev/null
+++ b/jhMaster/JSearch/client/com/sun/java/help/search/RAFFileFactoryOn12.java
@@ -0,0 +1,121 @@
+/*
+ * @(#)RAFFileFactoryOn12.java	1.4 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @(#) RAFFileFactoryOn12.java 1.4 - last change made 10/30/06
+ */
+
+package com.sun.java.help.search;
+
+import java.io.*;
+import java.net.URLConnection;
+import java.security.Permission;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.PrivilegedExceptionAction;
+import java.security.PrivilegedActionException;
+
+/**
+ * This Factory assumes we are on JDK 1.2
+ */
+
+final public class RAFFileFactoryOn12 {
+    /**
+     * Creata a RAFFile from a URLConnection.  Try to use a temporary file
+     * if possible.  This is a static public method
+     *
+     * @param url The URL with the data to the file
+     * @return the RAFFile for this data
+     * @exception IOException if there is problem reading from the file
+     */
+    public static RAFFile get(final URLConnection connection) throws IOException {
+	RAFFile topBack = null;
+
+	debug("get on "+connection);
+	final Permission permission = connection.getPermission();
+	
+	/* get the permission after the connection is established */
+	int dictLength = connection.getContentLength();
+	
+	try { 
+	    topBack = (RAFFile)
+		AccessController.doPrivileged(new PrivilegedExceptionAction() {
+		    
+		    RAFFile back = null;
+		    public Object run() throws IOException {
+			InputStream in = null;
+			OutputStream out = null;
+			try {
+			    File tmpFile = File.createTempFile("dict_cache", null);
+			    tmpFile.deleteOnExit();
+
+			    if (tmpFile != null) {
+				in = connection.getInputStream();
+				out  = new FileOutputStream(tmpFile);
+				int read = 0;
+				byte[] buf = new byte[BUF_SIZE];
+				while ((read = in.read(buf)) != -1) {
+				    out.write(buf, 0, read);
+				}
+				back = new TemporaryRAFFile(tmpFile, permission);
+			    }  else {
+				back = new MemoryRAFFile(connection);
+			    }
+			} finally {
+			    if (in != null) {
+				in.close();
+			    }
+			    if (out != null) {
+				out.close();
+			    }
+			}
+			return back;
+		    }
+		});
+	} catch (PrivilegedActionException pae) {
+	    topBack = new MemoryRAFFile(connection);
+	} catch (SecurityException se) {
+	    topBack = new MemoryRAFFile(connection);
+	}
+	return topBack;
+    }
+
+    // The size of the buffer
+    private static int BUF_SIZE = 2048;
+
+    /**
+     * Debug code
+     */
+
+    private static final boolean debug = false;
+    private static void debug(String msg) {
+        if (debug) {
+            System.err.println("RAFFileFactoryOn12: "+msg);
+        }
+    }
+}
+
diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/RoleFiller.java b/jhMaster/JSearch/client/com/sun/java/help/search/RoleFiller.java
new file mode 100644
index 0000000000000000000000000000000000000000..f29b00c8e85dc87de6eae68a3e6ced34a6825541
--- /dev/null
+++ b/jhMaster/JSearch/client/com/sun/java/help/search/RoleFiller.java
@@ -0,0 +1,198 @@
+/*
+ * @(#)RoleFiller.java	1.6 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @date   1/13/98
+ * @author Jacek R. Ambroziak
+ * @group  Sun Microsystems Laboratories
+ */
+
+package com.sun.java.help.search;
+
+import java.io.PrintStream;
+
+class RoleFiller
+{
+  static int Threshold = 300;
+
+  private ConceptData _conceptData;
+  private byte        _fixedRole;
+  private short        _filled;
+  private int        _begin;
+  private int        _end;
+  private int        _limit;
+  private RoleFiller       _next;
+  private RoleFiller[]     _fillers;
+  
+  public static final RoleFiller STOP = new RoleFiller();
+  
+  private RoleFiller() {}
+
+  public RoleFiller(int nColumns, ConceptData first, int role,
+		    int pos, int limit)
+  {
+    _conceptData = first;
+    _fixedRole = (byte)role; // primary/constitutive concept/role
+    _filled = (short)(1 << _fixedRole);
+    _begin = pos;		// offset in file
+    _end = _begin + first.getConceptLength();
+    _limit = limit;
+    _next = null;
+    _fillers = new RoleFiller[nColumns];
+    _fillers[role] = this;
+  }
+
+  public void print(PrintStream out) {
+    out.println(_begin + ", " + _end);
+  }
+  
+  void makeQueryHit(Query q, int nColumns, int doc, double penalty)
+  {
+    if (q.goodEnough(penalty))
+      {
+	int[] array =
+	  q.getConceptArrayOfNewHit(penalty,
+				    new Location(doc, _begin, _end));
+	for (int i = 0; i < nColumns; i++)
+	  array[i] = (_filled & 1 << i) != 0 ? _fillers[i].getConcept() : 0;
+      }
+  }
+
+  boolean isHit() {
+    return _filled > (1 << _fixedRole);
+  }
+  
+  double getScore() {
+    return _conceptData.getScore();
+  }
+  
+  int getConcept() {
+    return _conceptData.getConcept();
+  }
+  
+  RoleFiller next() {
+    return _next;
+  }
+  
+  void use(RoleFiller[] place, int index)
+  {
+    if (place[index] != null)
+      {
+	RoleFiller rf = place[index];
+	place[index] = this;
+	_next = rf;
+	while (rf._limit >= _begin)
+	  {
+	    // check if we can grow/improve a hit
+	    // we don't ever replace filler's fixed role
+	    if (_fixedRole != rf._fixedRole)
+	      {
+		if ((rf._filled & (1 << _fixedRole)) == 0) // not filled yet
+		  {
+		    rf._filled |= 1 << _fixedRole;
+		    rf._fillers[_fixedRole] = this;
+		    rf._end = _end;
+		  }
+		else
+		  rf.considerReplacementWith(this);
+	      }
+	      
+	    if (rf._next != null)
+	      rf = rf._next;
+	    else
+	      return;
+	  }
+      }
+    else
+      place[index] = this;
+  }
+  
+  private void considerReplacementWith(RoleFiller replacement)
+  {
+    // !!! simplistic for now
+    // needs gap and out of order
+    int role = replacement._fixedRole;
+    if (replacement.getScore() > _fillers[role].getScore())
+      _fillers[role] = replacement;
+  }
+
+  private double penalty(Query query, int nColumns)
+  {
+    int length = _end - _begin + 1;
+    double penalty = query.lookupPenalty(_filled);
+    // !!! here is a chance to check against query if hit worth scoring further
+    // might not be if query already has lots of good hits
+    for (int i = 0; i < nColumns; i++)
+      if ((_filled & (1 << i)) != 0)
+	{
+	  penalty += _fillers[i]._conceptData.getPenalty();
+	  length -= _fillers[i]._conceptData.getConceptLength() + 1;
+	  if ((_filled >> (i + 1)) != 0)
+	    for (int j = i + 1; j < nColumns; j++)
+	      if ((_filled & 1 << j) != 0 && _fillers[j]._begin < _begin)
+		penalty += query.getOutOufOrderPenalty();
+	}
+    return penalty + length*query.getGapPenalty();
+  }
+  
+  public void scoreList(Query query, int document)
+  {
+    int nColumns = query.getNColumns();
+    RoleFiller candidateHit = this; // function called for the head of list
+    RoleFiller next;		// lookahead: if overlap, if so, is it better
+
+    // 'candidateHit' always points at the current candidate to be converted to a QueryHit
+    // 'penalty' is its penalty
+    // 'next' is used to explore earlier overlapping fillers
+    // the decision to emit a QueryHit is made when either there's no next
+    // or next doesn't overlap the current candidate
+    // the loop's logic makes sure that at emit time there's no better/earlier filler
+    // to overlap with the candidate
+
+    double penalty = candidateHit.penalty(query, nColumns);
+  
+    for (next = candidateHit._next; next != null; next = next._next)
+      if (next._end < candidateHit._begin) // no overlap
+	{
+	  candidateHit.makeQueryHit(query, nColumns, document, penalty);
+	  candidateHit = next;
+	  penalty = candidateHit.penalty(query, nColumns);
+	}
+      else
+	{
+	  // !!! can be computed in two steps
+	  double penalty2 = next.penalty(query, nColumns);
+	  if (penalty2 <= penalty)	// prefer next, disregard candidateHit
+	    {
+	      penalty = penalty2;
+	      candidateHit = next;
+	    }
+	}
+    candidateHit.makeQueryHit(query, nColumns, document, penalty);
+  }
+
+}
diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/Rule.java b/jhMaster/JSearch/client/com/sun/java/help/search/Rule.java
new file mode 100644
index 0000000000000000000000000000000000000000..39204bcbfecc4e6c31d3102607b07be1b65bb2c2
--- /dev/null
+++ b/jhMaster/JSearch/client/com/sun/java/help/search/Rule.java
@@ -0,0 +1,245 @@
+/*
+ * @(#)Rule.java	1.3 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @(#) Rule.java 1.3 - last change made 10/30/06
+ */
+
+package com.sun.java.help.search;
+
+import java.util.Vector;
+import java.util.StringTokenizer;
+
+/**
+ * A Rule matches a pattern at the right ends of a word, removes an indicated
+ * number of characters from the end to produce a stem, and generate a list
+ * of alternative forms of the word by adding each of a specified list of
+ * endings to the stem.  
+ * <p>
+ * Each rule specifies an ending pattern and a list
+ * of endings to be added to the stem to produce different variant forms
+ * of the input word.  The ending pattern consists of a string of letters
+ * or letter groups separated by spaces to be matched against corresponding
+ * letters at the end of the word.  
+ * <ul>
+ * <li>
+ * A letter group (e.g., aeiou) will match any of the letters in the group.  
+ * <li> 
+ * A letter group prefixed with a period (.) may be matched anywhere 
+ * preceding the match of its subsequent letter group.  A letter group 
+ * of this type is referred to as "unanchored." 
+ * <li>
+ * A group that is to be matched at a specified position is "anchored." 
+ * <li>
+ * A plus sign (+) in the pattern, in place of a letter group, marks the
+ * point in the pattern after which the matching letters will be removed
+ * to form the stem.  There should be no unanchored letter groups after
+ * the plus sign, and there should be at most one plus sign in the pattern
+ * (otherwise only the leftmost will count).  
+ * <li>
+ * An ampersand (&) in place of
+ * a letter group in an ending pattern will match a letter that is the same
+ * as its preceeding letter in the word.  
+ * <li>
+ * An ampersand in the list of alternative endings indicates a repeat of
+ * the letter that ends the stem. 
+ * <li>
+ * An under bar (_) as an alternative ending indicates that nothing is to
+ * be added to the stem for that alternative.  
+ * <li>
+ * An ending beginning with an
+ * asterisk (*) indicates that the rules are to be reapplied recursively to
+ * the form obtained from using this ending.
+ * </ul>
+ * <p>
+ * Rule(s) are grouped in blocks and labeled (usually by a common final
+ * sequence) and are ordered within each group so that after a matching
+ * rule is found no further rules are to be tried (except when invoked
+ * explicitly on a new word by a redo (*) operator in an alternative ending).
+ *
+ * @author Roger D. Brinkley
+ * @author Jacek Ambroziak
+ * @version	1.3	10/30/06
+ *
+ * @see LiteMorph
+ */
+
+public class Rule {
+    private String[] pattern;
+    private int killnum=0;
+    private String[] expansions;
+    private Vector words;
+    private LiteMorph morph;
+
+    /**
+     * Create a Rule
+     * @param expression A String representing the ending patern described previously.
+     * @param expansionString A String of space delimeted expansions as described previously.
+     */
+    public Rule(String expression, String expansionString, LiteMorph morph) {
+	String chars;
+	boolean passedPlus = false;
+
+	this.morph = morph;
+
+	//set up pattern array:
+
+	if (expression.length() > 0) {
+	    Vector patternBuffer = new Vector(expression.length());
+	    StringTokenizer temp = new StringTokenizer(expression, " \t\n\r");
+	    while (temp.hasMoreTokens()) {
+		if (passedPlus) {
+		    // count number of characters after +
+		    killnum++; 
+		}
+		chars = temp.nextToken();
+		if (chars.equals("+")) {
+		    passedPlus = true;
+		} else {
+		    patternBuffer.addElement(chars);
+		}
+	    }
+	    pattern = new String[patternBuffer.size()];
+	    patternBuffer.copyInto(pattern);
+	}
+	else pattern =  new String[0];
+
+	//set up expansions array:
+	if (expansionString.length() > 0) {
+	    Vector expansionsBuffer = new Vector(expansionString.length());
+	    StringTokenizer temp = new StringTokenizer(expansionString, ", \t\n\r");
+	    while (temp.hasMoreTokens()) {
+		expansionsBuffer.addElement(temp.nextToken());
+	    }
+	    expansions = new String[expansionsBuffer.size()];
+	    expansionsBuffer.copyInto(expansions);
+	}
+	else {
+	    expansions = new String[0];
+	}
+    }
+    
+    /**
+     * Determines if a word matches the rule
+     */
+    public String [] match(String word, int depth, int skipnum) {
+	words = new Vector();
+	boolean matched = true;
+	
+	//skipnum positions have already been
+	//tested by the dispatch method
+	int position = word.length()-1-skipnum;
+	int i = pattern.length-1-skipnum;
+	while (i > -1) {
+	    debug("   trying "+pattern[i]+" at "+position+
+		  " for i = "+i);
+	    // There isn't anything left to test
+	    // the match failed
+	    if (position<0) {
+		matched = false;
+		break;
+	    }
+
+	    //"&" match duplicate of previous letter
+	    if (pattern[i].equals("&")) {
+		if (position < 1 || word.charAt(position) != word.charAt(position-1)) {
+		    matched = false;
+		    break;
+		}
+		else i--;
+	    }
+
+	    //"." pattern can match anywhere
+	    else if (pattern[i].startsWith(".")) { 
+		if (pattern[i].indexOf(word.charAt(position), 1) >= 0) {
+		    //it matches here, so go to next pattern element
+		    i--; 
+		}
+	    } else if (pattern[i].indexOf(word.charAt(position))<0) {
+		// doesn't match here
+		matched = false;
+		break;
+	    } else  {
+		i--;
+	    }
+	    position--;
+	}
+
+	// All done with the compares. If we've got a match then
+	// build the list words from the expansion list
+	if (matched)
+	    {
+		String stem = word.substring(0, word.length() - killnum);
+		for (i = 0; i < expansions.length; i++) {
+		    makeForm(stem, expansions[i], depth);
+		}
+	    }
+	String[] result = new String[words.size()];
+	words.copyInto(result);
+	words = null;
+	return result;
+    }
+
+    
+    private void makeForm(String stem, String expansion, int depth) {
+	switch (expansion.charAt(0)) {
+	case '_':
+	    // just use the stem; nothing to add
+	    words.addElement(stem);
+	    break;
+	
+	case '&':
+	    // double last letter of stem
+	    words.addElement(stem + stem.charAt(stem.length() - 1) + expansion.substring(1));
+	    break;
+	
+	case '*':
+	    // redo MorphWord on the resulting form
+	    debug(" starting redo: with "+stem+" + "+expansion+
+		  " from depth "+depth);
+	    if (expansion.charAt(1) == '_')
+		morph.morphWord(stem, depth + 1);
+	    else
+		morph.morphWord(stem + expansion.substring(1), depth + 1);
+	    break;
+
+	default:
+	    words.addElement(stem + expansion);
+	    break;
+	}
+    }
+    /**
+     * For printf debugging.
+     */
+    private static final boolean debugFlag = false;
+    private static void debug(String str) {
+        if( debugFlag ) {
+            System.out.println("Rule: " + str);
+        }
+    }
+}
+  
diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/Schema.java b/jhMaster/JSearch/client/com/sun/java/help/search/Schema.java
new file mode 100644
index 0000000000000000000000000000000000000000..5d259a6d8fbc2e9de79bf8acabaa99265c8f6e66
--- /dev/null
+++ b/jhMaster/JSearch/client/com/sun/java/help/search/Schema.java
@@ -0,0 +1,194 @@
+/*
+ * @(#)Schema.java	1.11 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @version	1.5	03/18/98
+ * @author Jacek R. Ambroziak
+ */
+
+package com.sun.java.help.search;
+
+import java.util.Vector;
+import java.util.Hashtable;
+import java.util.StringTokenizer;
+import java.net.URL;
+import java.net.URLConnection;
+import java.io.*;
+
+public class Schema
+{
+  private String _dirName;
+  private URL _hsBase = null;
+  private boolean _update;
+  private Vector _lines = new Vector();
+
+  public static void main(String[] args)
+  {
+    try {
+      Schema sch = new Schema(null, "/files/resources/lexicon/LIF_ONT", false);
+      debug(sch.parametersAsString("EDGE"));
+      debug(sch.parametersAsString("TMAP"));
+      debug(sch.parameters("EDGE").get("rt").toString());
+      debug(sch.parameters("EDGE").get("vl").toString());
+    }
+    catch (Exception e) {
+      e.printStackTrace();
+    }
+  }
+
+  public Schema(URL base, String dirName, boolean update) throws Exception
+  {
+    _hsBase = base;
+    _dirName = dirName;
+    _update = update;
+    try {
+      read();
+    }
+    catch (java.io.FileNotFoundException e) {
+      debug("error creating SCHEMA");
+    }
+    for (int i = 0; i < _lines.size(); i++)
+      debug(_lines.elementAt(i).toString());
+  }
+  
+  public void update(String partName, String parameters)
+  {
+    for (int i = 0; i < _lines.size(); i++)
+      if (((String)_lines.elementAt(i)).startsWith(partName))
+	_lines.removeElementAt(i);
+    _lines.addElement(partName + " " + parameters);
+  }
+
+  public String parametersAsString(String name)
+  {
+    for (int i = 0; i < _lines.size(); i++)
+      if (((String)_lines.elementAt(i)).startsWith(name))
+	return ((String)_lines.elementAt(i)).substring(name.length() + 1);
+    return null;
+  }
+
+  public Hashtable parameters(String name)
+  {
+    for (int i = 0; i < _lines.size(); i++)
+      if (((String)_lines.elementAt(i)).startsWith(name))
+	{
+	  Hashtable result = new Hashtable();
+	  StringTokenizer tokens =
+	    new StringTokenizer((String)_lines.elementAt(i), " =");
+	  tokens.nextToken();		// skip name
+	  while (tokens.hasMoreTokens())
+	    result.put(tokens.nextToken(), tokens.nextToken());
+	  return result;
+	}
+    return null;
+  }
+
+  public URL getURL(String name) throws Exception
+  {
+    URL baseURL=null, url, tmapURL=null;
+    URLConnection connect;
+    File file;
+    
+    debug("getURL " + name);
+    debug("dirName=" + _dirName + " hsBase= " + _hsBase);
+
+    if (_hsBase == null) {
+	file = new File(_dirName);
+	if (file.exists()) {
+	    // On Win32 we need to convert all "\" to "/"
+	    if (File.separatorChar != '/') {
+		_dirName = _dirName.replace(File.separatorChar, '/');
+	    }
+	    // Make sure the last character is a file separator
+	    if (_dirName.lastIndexOf('/')
+		!= _dirName.length() - 1) {
+		_dirName = _dirName.concat("/");
+	    }
+	    debug ("file:" + _dirName);
+	    // Use a file protocol
+	    baseURL = new URL("file", "", _dirName);
+	} else {
+	// Assume that some protocol was specified and try it
+	baseURL = new URL(_dirName);
+      }
+    }
+      
+    // Read the SCHEMA data
+    if (_hsBase != null) {
+      return new URL(_hsBase, _dirName + "/" + name);
+    } else {
+      return new URL(baseURL, name);
+    }
+  }
+
+  public void save()
+  {
+    if (_update) {
+      try {
+	FileWriter out = new FileWriter(_dirName + "/SCHEMA");
+	out.write("JavaSearch 1.0\n");
+	for (int i = 0; i < _lines.size(); i++)
+	  {
+	    out.write((String)_lines.elementAt(i));
+	    out.write('\n');
+	  }
+	out.close();
+      }
+      catch (IOException e) {
+	System.err.println("SCHEMA save failed " + e);
+      }
+    }
+  }
+  
+  private void read() throws Exception
+  {
+    URL url;
+    URLConnection connect;
+    BufferedReader in;
+
+    url = getURL("SCHEMA");
+    connect = url.openConnection();
+    in = new BufferedReader
+      (new InputStreamReader(connect.getInputStream()));
+
+    // This needs to be replaced with our XML Parser
+    String line;
+    while ((line = in.readLine()) != null)
+      _lines.addElement(line);
+    in.close();
+  }
+  
+  /**
+   * For printf debugging.
+   */
+  private static boolean debugFlag = false;
+  private static void debug(String str) {
+    if( debugFlag ) {
+      System.out.println("Schema: " + str);
+    }
+  }
+}
diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/Search.java b/jhMaster/JSearch/client/com/sun/java/help/search/Search.java
new file mode 100644
index 0000000000000000000000000000000000000000..1389238e1c908dc8c35b48d714a503a73aeac222
--- /dev/null
+++ b/jhMaster/JSearch/client/com/sun/java/help/search/Search.java
@@ -0,0 +1,422 @@
+/*
+ * @(#)Search.java	1.17 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @date   1/13/98
+ * @author Jacek R. Ambroziak
+ * @group  Sun Microsystems Laboratories
+ */
+
+package com.sun.java.help.search;
+
+import java.io.*;
+import javax.help.search.SearchQuery;
+
+class Search
+{
+  private static final int InitNConcepts = 128;
+  
+  private SearchEnvironment _env;
+  private int _max;
+  private int _nConcepts;
+  private int _nQueries;
+  private ConceptGroupGenerator _firstGenerator = new ConceptGroupGenerator();
+  private int[] _concepts = new int[DocumentCompressor.NConceptsInGroup];
+  private int _free2;
+  private int _size2;
+  private int _startingIndex = 0;
+  private int _limit = 0;
+  private Query[] _query;
+  private ConceptData[] _conceptData;
+  private GeneratorHeap _genHeap = new GeneratorHeap();
+  private int _document;
+  private byte[] _data = null;
+  private int _base = 0;	// index into _data
+  private NextDocGeneratorHeap _nextDocGenHeap = new NextDocGeneratorHeap();
+  private IntegerArray _kTable = new IntegerArray();
+  private IntegerArray _offsets = new IntegerArray();
+  private IntegerArray _maxConcepts = new IntegerArray();
+
+  private IntegerArray _docConcepts = new IntegerArray();
+  private IntegerArray _queryMasks = new IntegerArray();
+  private int _maxHitsToShow = 100;
+
+  public Search(SearchEnvironment se, int nColumns)
+  {
+    _env = se;
+    _nQueries = 1;
+    _query = new Query[_nQueries];
+
+    _size2 = InitNConcepts;
+    _free2 = 0;
+    _conceptData = new ConceptData[_size2];
+
+    _query[0] = new Query(se, nColumns, null);
+    /*
+      _query[1] = new Query(se, 3, null);
+      _query[2] = new Query(se, 3, null);
+      _query[3] = new Query(se, 3, null);
+      */
+  }
+
+  public void addTerm(int col, int concept, double score, int query)
+  {
+    if (_env.occursInText(concept))
+      {
+	if (_free2 == _size2)
+	  {
+	    ConceptData[] newArray = new ConceptData[_size2 *= 2];
+	    System.arraycopy(_conceptData, 0, newArray, 0, _free2);
+	    _conceptData = newArray;
+	  }
+	_conceptData[_free2++] =
+	  new ConceptData(concept, col, score, query,
+			  _query[query].getNColumns());
+      }
+  }
+  
+  public void startSearch(SearchQuery searchQuery)
+  {
+    //  fprintf(stderr, "startSearch: setup\n");
+    int i, j;
+    // set up ConceptData lists
+    // order search terms
+    quicksort(0, _free2 - 1);
+    // remove duplicates
+    for (i = 0; i < _free2 - 1; i = j)
+      for (j = i + 1; j < _free2; j++)
+	if (_conceptData[i].crqEquals(_conceptData[j]))
+	  _conceptData[j] = null;
+	else
+	  i = j;
+    // create lists
+    for (i = 0; i < _free2 - 1; i = j)
+      for (j = i + 1; j < _free2; j++)
+	if (_conceptData[j] != null)
+	  if (_conceptData[i].cEquals(_conceptData[j]))
+	    {
+	      _conceptData[i].addLast(_conceptData[j]);
+	      _conceptData[j] = null;
+	    }
+	  else
+	    i = j;
+    // densify
+    for (i = 0; i < _free2 - 1; i++)
+      if (_conceptData[i] == null)
+	for (j = i + 1; j < _free2; j++)
+	  if (_conceptData[j] != null)
+	    {
+	      _conceptData[i] = _conceptData[j];
+	      _conceptData[j] = null;
+	      break;
+	    }
+    // set up new document generators
+    _nextDocGenHeap.reset();
+    for (i = 0; i < _free2 && _conceptData[i] != null; i++)
+      {
+	NextDocGenerator gen = new NextDocGenerator(_conceptData[i], _env);
+	try {
+	  gen.first();
+	  if (gen.getDocument() != NonnegativeIntegerGenerator.END)
+	    {
+	      _conceptData[i].
+		setConceptLength(_env.
+				 getConceptLength(_conceptData[i].getConcept()));
+	      _nextDocGenHeap.addGenerator(gen);
+	    }
+	}
+	catch (Exception e) {
+	  e.printStackTrace();
+	}
+      }
+    _nextDocGenHeap.start(); 
+    searchDocument();
+    if (searchQuery == null) {
+	printResults(_maxHitsToShow);
+    } else {
+	_query[0].makeEvent(_maxHitsToShow, searchQuery);
+    }
+  }
+
+  private void searchDocument()
+  {
+    RoleFiller[] start = new RoleFiller[_nQueries];
+    do {
+      try {
+	switch (nextDocument(start))
+	  {
+	  case 0:		// multi group
+	    _genHeap.start(start);
+	    while (_genHeap.next(start))
+	      ;
+	    break;
+	    
+	  case 1:		// single group
+	    if (_firstGenerator.next())
+	      {
+		_firstGenerator.generateFillers(start);
+		while (_firstGenerator.next())
+		  _firstGenerator.generateFillers(start);
+	      }
+	    break;
+	    
+	  case 2:		// reached the end
+	    return;
+	  }
+      }
+      catch (Exception e) {
+	e.printStackTrace(System.err);
+	continue;
+      }
+      
+      for (int i = 0; i < _nQueries; i++)
+	{
+	  RoleFiller next;
+	  if ((next = start[i]) != null && next != RoleFiller.STOP)
+	    next.scoreList(_query[i], _document);
+	  
+	}
+      _genHeap.reset();
+    }
+    while (_nextDocGenHeap.isNonEmpty());
+  }
+  
+  // will be called for increasing values of c
+  // searches index interval [_startingIndex, _nConcepts]
+  // saves state in _startingIndex
+  private int indexOf(int concept) throws Exception
+  {
+    int i = _startingIndex, j = _nConcepts, k;
+    while (i <= j)
+      if (_concepts[k = (i + j)/2] < concept)
+	i = k + 1;
+      else if (concept < _concepts[k])
+	j = k - 1;
+      else
+	{
+	  _startingIndex = k + 1;
+	  return k;
+	}
+    throw new Exception("indexOf " + concept + " not found");
+  }
+
+  private void printResults(int nHits)
+  {
+    for (int q = 0; q < _nQueries; q++)
+      {
+	System.out.println("query " + q);
+	if (_query[q] != null)
+	  _query[q].printHits(nHits);
+      }
+  }
+
+  private ConceptGroupGenerator makeGenerator(int group) throws Exception
+  {
+    int shift, index;
+  
+    if (group > 0)
+      {
+	index = _base + _offsets.at(group - 1);
+	shift = _maxConcepts.at(group - 1);
+      }
+    else
+      {
+	index = _base;
+	shift = 0;
+      }
+  
+    // initialize generator
+    ConceptGroupGenerator gen =
+      new ConceptGroupGenerator(_data, index, _kTable.at(2*group + 1));
+    // decode concept table
+    _nConcepts = gen.decodeConcepts(_kTable.at(2*group), shift, _concepts);
+    if (group < _limit)
+      _max = _concepts[_nConcepts] = _maxConcepts.at(group);
+    else
+      _max = _concepts[_nConcepts - 1];
+    _genHeap.addGenerator(gen);
+    _startingIndex = 0;		// in _concepts; lower search index
+    return gen;
+  }
+
+  // returns true if multigroup
+  private boolean openDocumentIndex(int docID) throws Exception
+  {
+      // The data is only the data for this document id. Thus the base is set
+      // to zero.
+    _data = _env.getPositions(docID);
+    _base = 0;
+    _startingIndex = 0;
+    int kk = _data[_base] & 0xFF, k2;
+    switch (kk >> 6)		// get type
+      {
+      case 0:			// single group, no extents
+	k2 = _data[_base + 1];
+	_firstGenerator.init(_data, _base += 2, k2);
+	// decode concept table
+	_nConcepts = _firstGenerator.decodeConcepts(kk & 0x3F, 0, _concepts);
+	return false;
+      
+      case 2:			// multi group, no extents
+	_kTable.clear();
+	_offsets.clear();
+	_maxConcepts.clear();
+	ByteArrayDecompressor compr =
+	  new ByteArrayDecompressor(_data, _base + 1);
+	compr.decode(kk & 0x3F, _kTable);
+	compr.ascDecode(_kTable.popLast(), _offsets);
+	compr.ascDecode(_kTable.popLast(), _maxConcepts);
+	_base += 1 + compr.bytesRead();
+	_limit = _maxConcepts.cardinality();
+	return true;
+      
+      case 1:			// single group, extents
+      case 3:			// multi group, extents
+	throw new Exception("extents not yet implemented\n");
+      }
+    return false;
+  }
+
+  private int nextDocument(RoleFiller[] start) throws Exception
+  {
+    while (_nextDocGenHeap.isNonEmpty())		// still something to do
+      {
+	for (int i = 0; i < _nQueries; i++)
+	  if (_query[i] != null)
+	    _query[i].resetForNextDocument();
+      
+	// gather all concepts this document has and store associated conceptData
+	int index = 0;
+	_document = _nextDocGenHeap.getDocument();
+	_docConcepts.clear();
+	_queryMasks.clear();
+	do {
+	  _docConcepts.add(_nextDocGenHeap.getConcept());
+	  _queryMasks.add(_nextDocGenHeap.getQueryMask());
+	  (_conceptData[index++] = _nextDocGenHeap.getTerms()).runBy(_query);
+	  _nextDocGenHeap.step();
+	}
+	while (_nextDocGenHeap.atDocument(_document));
+
+	// if there is no saturation model, some query will always vote YES
+	// and so every document will be opened
+	// even if this case, however, savings can be achieved by not generating fillers
+	// for some queries (not scoring, etc)
+	// and, with more care, creation of some GroupGenerators can be avoided
+	// saturating queries with lots of good hits will lead to best results
+	int voteMask = 0;
+	for (int i = 0; i < _nQueries; i++)
+	  if (_query[i] != null)
+	    if (_query[i].vote())
+	      {
+		start[i] = null;	// normal reset
+		voteMask |= 1 << i;
+	      }
+	    else
+	      start[i] = RoleFiller.STOP;	// prohibit setting
+      
+	// we may eliminate some ConceptGroupGenerators
+	// those which would be used only by Queries which voted NO
+	if (voteMask != 0)		// need to open up document
+	  {
+	    ConceptGroupGenerator gen;
+	    // !!! don't gather Fillers for disinterested Queries
+	    if (openDocumentIndex(_document)) // multi group
+	      {
+		// set up all needed generators
+		int i = 0;
+		while ((_queryMasks.at(i) & voteMask) == 0)
+		  ++i;
+		//		assert(i < index);
+		int c = _docConcepts.at(i);
+		int group = 0;
+		// find first group
+		while (c > _maxConcepts.at(group) && ++group < _limit)
+		  ;
+		gen = makeGenerator(group);
+		gen.addTerms(indexOf(c), _conceptData[i]);
+	      
+		for (++i; i < index; i++)
+		  if ((_queryMasks.at(i) & voteMask) > 0)
+		    {
+		      c = _docConcepts.at(i);
+		      if (c > _max)	// need to find another group
+			{
+			  //			  assert(group < _limit);
+			  while (c > _maxConcepts.at(group) && ++group < _limit)
+			    ;
+			  gen = makeGenerator(group);
+			}
+		      gen.addTerms(indexOf(c), _conceptData[i]);
+		    }
+		return 0;
+	      }
+	    else			// single group
+	      {
+		for (int i = 0; i < index; i++)
+		  if ((_queryMasks.at(i) & voteMask) != 0)
+		    _firstGenerator.addTerms(indexOf(_docConcepts.at(i)),
+					     _conceptData[i]);
+		return 1;
+	      }
+	  }
+      }
+    return 2;
+  }
+
+  // part of quicksearch
+  private int partition(int p, int r)
+  {
+    ConceptData x = _conceptData[p];
+    int i = p - 1, j = r + 1;
+    while (true)
+      {
+	while (x.compareWith(_conceptData[--j]))
+	  ;
+	while (_conceptData[++i].compareWith(x))
+	  ;
+	if (i < j)
+	  {
+	    ConceptData t = _conceptData[i];
+	    _conceptData[i] = _conceptData[j];
+	    _conceptData[j] = t;
+	  }
+	else
+	  return j;
+      }
+  }
+
+  private void quicksort(int p, int r)
+  {
+    if (p < r)
+      {
+	int q = partition(p, r);
+	quicksort(p, q);
+	quicksort(q + 1, r);
+      }
+  }
+}
diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/SearchEnvironment.java b/jhMaster/JSearch/client/com/sun/java/help/search/SearchEnvironment.java
new file mode 100644
index 0000000000000000000000000000000000000000..8a35ca450214602f858793b0b4be79f27f751348
--- /dev/null
+++ b/jhMaster/JSearch/client/com/sun/java/help/search/SearchEnvironment.java
@@ -0,0 +1,375 @@
+/*
+ * @(#)SearchEnvironment.java	1.29 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @(#) SearchEnvironment.java 1.11 - last change made 04/19/98
+ */
+
+package com.sun.java.help.search;
+
+import javax.help.search.SearchItem;
+import java.io.*;
+import java.util.Vector;		// consider removal
+import java.net.URL;
+import java.net.URLConnection;
+import java.net.MalformedURLException;
+import java.util.Locale;
+import java.awt.datatransfer.DataFlavor;
+import java.lang.reflect.Method;
+
+/**
+ * This class established a SearchEnvironment for JavaHelp classes
+ *
+ * @version	1.11	04/19/98
+ * @author Jacek R. Ambroziak
+ * @author Roger D. Brinkley
+ */
+
+class SearchEnvironment {
+  private IntegerArray concepts;
+  private IntegerArray offsets;
+  private byte[]       allLists;
+
+  private IntegerArray concepts3;
+  private IntegerArray offsets3;
+  private byte[]       allChildren;
+
+  
+  private IntegerArray documents;
+  private IntegerArray offsets2;
+  private IntegerArray titles;
+
+  private RAFFile positionsFile = null;
+  private byte[]  positions;
+  
+  private ByteArrayDecompressor compr;
+  
+  private BtreeDict tmap;
+  
+  private URL base;		// the base for all searches
+  private String indexDir;	// the index directory
+
+
+  public SearchEnvironment(String indexDir, URL hsBase) throws Exception {
+    this.base = hsBase;
+    this.indexDir = indexDir;
+
+    readFromDB();
+    compr = new ByteArrayDecompressor(null, 0);
+  }
+
+  public int fetch(String conceptName) throws Exception {
+    return tmap.fetch(conceptName);
+  }
+  
+  public String fetch(int conceptID) throws Exception {
+    return tmap.fetch(conceptID);
+  }
+  
+  public SearchItem makeItem(QueryHit hit) throws Exception
+  {
+    Vector concepts = new Vector();
+    int[] conceptIDs = hit.getArray();
+    for (int i = 0; i < conceptIDs.length; i++) {
+      if (conceptIDs[i] > 0) {
+	concepts.addElement(fetch(conceptIDs[i]));
+      }
+    }
+
+    int begin = hit.getBegin();
+    int end = hit.getEnd();
+    return new SearchItem(this.base,
+			  fetch(titles.at(hit.getDocument())),
+			  Locale.getDefault().toString(),
+			  fetch(documents.at(hit.getDocument())),
+			  hit.getScore(),
+			  begin,
+			  end, 
+			  concepts);
+  }
+
+  public String hitToString(QueryHit hit) throws Exception
+  {
+    StringBuffer result = new StringBuffer();
+    result.append(hit.getScore());
+    result.append(" ");
+    result.append(fetch(documents.at(hit.getDocument())));
+    if (false) {
+      result.append(" ");
+      result.append(fetch(titles.at(hit.getDocument())));
+    }
+    result.append(" [");
+    int begin = hit.getBegin();
+    int end = hit.getEnd();
+    result.append(begin);
+    result.append(", ");
+    result.append(end);
+    result.append("], {");
+    int[] concepts = hit.getArray();
+    for (int i = 0; i < concepts.length; i++)
+      {
+	if (concepts[i] > 0)
+	  result.append(fetch(concepts[i]));
+	else
+	  result.append("--");
+	if (i < concepts.length - 1)
+	  result.append(", ");
+      }
+    result.append("}");
+    return result.toString();
+  }
+  
+  public byte[] getPositions(int docId) throws java.io.IOException
+  {
+      // Later on we should do some caching of this
+      int offset = offsets2.at(docId);
+      int upto;
+      if (docId+1 == offsets2.cardinality()) {
+	  upto = (int)positionsFile.length();
+      } else {
+	  upto = offsets2.at(docId+1);
+      }
+      positions = new byte[upto - offset];
+      positionsFile.seek(offset);
+      positionsFile.read(positions, 0, upto - offset);
+      return positions;
+  }
+
+  public int getDocumentIndex(int docId) {
+    return offsets2.at(docId);
+  }
+  
+  public void close() throws java.io.IOException {
+    positionsFile.close();
+  }
+
+  public boolean occursInText(int concept) {
+    return concepts.indexOf(concept) >= 0;
+  }
+
+  public NonnegativeIntegerGenerator getDocumentIterator(int concept)
+  {
+    int index = concepts.indexOf(concept);
+    if (index >= 0)
+      return new ConceptList(allLists, offsets.at(index));
+    else
+      return null;
+  }
+  
+  public NonnegativeIntegerGenerator getChildIterator(int concept)
+  {
+    int index = concepts3.indexOf(concept);
+    if (index >= 0)
+      return new ConceptList(allChildren, offsets3.at(index));
+    else
+      return null;
+  }
+  
+  public void getChildren(int concept, IntegerArray array) throws Exception
+  {
+    int index = concepts3.indexOf(concept);
+    if (index >= 0)
+      {
+	int where = offsets3.at(index);
+	compr.initReading(allChildren, where + 1);
+	compr.ascDecode(allChildren[where], array);
+      }
+  }
+  
+  public int getConceptLength(int concept) throws Exception {
+    return tmap.fetch(concept).length();
+  }
+  
+  // A temporary piece of code
+  // Should be rearranged as soon as possible
+
+  private URL getURL(String s) throws MalformedURLException {
+    URL hsBase = this.base;
+    String dir = this.indexDir;
+    URL back;
+    URL baseURL = null;
+    File file;
+
+    if (hsBase == null) {
+	file = new File(dir);
+	if (file.exists()) {
+	    // On Win32 we need to convert all "\" to "/"
+	    if (File.separatorChar != '/') {
+		dir = dir.replace(File.separatorChar, '/');
+	    }
+	    // Make sure the last character is a file separator
+	    if (dir.lastIndexOf('/')
+		!= dir.length() - 1) {
+		dir = dir.concat("/");
+	    }
+	    debug ("file:" + dir);
+	    // Use a file protocol
+	    baseURL = new URL("file", "", dir);
+	} else {
+	    // Assume that some protocol was specified and try it
+	  baseURL = new URL(dir);
+	}
+    }
+      
+    if (hsBase != null) {
+      back = new URL(hsBase, dir + "/" + s);
+    } else {
+      back = new URL(baseURL, s);
+    }
+
+    return back;
+  }
+
+  private void readChildrenData() throws Exception {
+    URL url;
+    URLConnection connect;
+    BufferedInputStream in;
+
+    // Read the Children.Tab data
+    try {
+      url = getURL("CHILDREN.TAB");
+      connect = url.openConnection();
+      InputStream ois = connect.getInputStream();
+      
+      if (ois == null) {
+	  concepts3 = new IntegerArray(1);
+	  return;
+      }
+
+      in = new BufferedInputStream(ois);
+
+      int k1 = in.read();
+      concepts3 = new IntegerArray(4096);
+      StreamDecompressor sddocs = new StreamDecompressor(in);
+      sddocs.ascDecode(k1, concepts3);
+      int k2 = in.read();
+      offsets3 = new IntegerArray(concepts3.cardinality() + 1);
+      offsets3.add(0);
+      StreamDecompressor sdoffsets = new StreamDecompressor(in);
+      sdoffsets.ascDecode(k2, offsets3);
+      in.close();
+    
+      // Read the Chilren data
+      url = getURL("CHILDREN");
+      connect = url.openConnection();
+      ois = connect.getInputStream();
+
+      if (ois == null) {
+	  concepts3 = new IntegerArray(1);
+	  return;
+      }
+
+      in = new BufferedInputStream(ois);
+      int length = connect.getContentLength();
+      allChildren = new byte[length];
+      in.read(allChildren);
+      in.close();
+    } catch (MalformedURLException e) {
+      concepts3 = new IntegerArray(1);
+    } catch (FileNotFoundException e2) {
+      concepts3 = new IntegerArray(1);
+    } catch (IOException e2) {
+      concepts3 = new IntegerArray(1);
+    }
+  }
+
+  private void readFromDB() throws Exception {
+    URL url;
+    URLConnection connect;
+    BufferedInputStream in = null;
+    
+    Schema schema = new Schema(base, indexDir, false);
+    BtreeDictParameters params = new BtreeDictParameters(schema, "TMAP");
+    params.readState();
+    tmap = new BtreeDict(params);
+
+    readChildrenData();
+
+    url = getURL("DOCS.TAB");
+    connect = url.openConnection();
+    in = new BufferedInputStream(connect.getInputStream());
+    int k1 = in.read();
+    concepts = new IntegerArray(4096);
+    StreamDecompressor sddocs = new StreamDecompressor(in);
+    sddocs.ascDecode(k1, concepts);
+    int k2 = in.read();
+    offsets = new IntegerArray(concepts.cardinality() + 1);
+    offsets.add(0);
+    StreamDecompressor sdoffsets = new StreamDecompressor(in);
+    sdoffsets.ascDecode(k2, offsets);     
+    in.close();
+
+    // Read the Lists data
+    url = getURL("DOCS");
+    connect = url.openConnection();
+    in = new BufferedInputStream(connect.getInputStream());
+    // Note: I'd rather look a the length in the URLConnection
+    // and read in all the data at once, but it doesn't work on 1.1
+    ByteArrayOutputStream data = new ByteArrayOutputStream();
+    byte [] buff = new byte[512];
+    int i = 0;
+    while ((i = in.read(buff)) != -1) {
+      data.write(buff, 0, i);
+    }
+    allLists = data.toByteArray();
+    in.close();
+
+    // Read the positions offset data
+    url = getURL("OFFSETS");
+    connect = url.openConnection();
+    in = new BufferedInputStream(connect.getInputStream());
+    k1 = in.read();
+    documents = new IntegerArray(4096);
+    sddocs = new StreamDecompressor(in);
+    sddocs.ascDecode(k1, documents);
+    k2 = in.read();
+    offsets2 = new IntegerArray(documents.cardinality() + 1);
+    sdoffsets = new StreamDecompressor(in);
+    sdoffsets.ascDecode(k2, offsets2);
+    // decompress titles' ids table
+    int k3 = in.read();
+    titles = new IntegerArray(documents.cardinality());
+    StreamDecompressor sdtitles = new StreamDecompressor(in);
+    sdtitles.decode(k3, titles);
+    in.close();
+
+    // Read in the Positions data
+    RAFFileFactory factory = RAFFileFactory.create();
+    url = getURL("POSITIONS");
+    positionsFile = factory.get(url, false);
+  }
+
+  /**
+   * For printf debugging.
+   */
+  private static boolean debugFlag = false;
+  private static void debug(String str) {
+    if( debugFlag ) {
+      System.out.println("SearchEnvironment: " + str);
+    }
+  }
+}
diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/StreamDecompressor.java b/jhMaster/JSearch/client/com/sun/java/help/search/StreamDecompressor.java
new file mode 100644
index 0000000000000000000000000000000000000000..b4d39b98cf9e50b3ea478d0b6a37ec17469c4f37
--- /dev/null
+++ b/jhMaster/JSearch/client/com/sun/java/help/search/StreamDecompressor.java
@@ -0,0 +1,95 @@
+/*
+ * @(#)StreamDecompressor.java	1.6 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @date   1/13/98
+ * @author Jacek R. Ambroziak
+ * @group  Sun Microsystems Laboratories
+ */
+
+package com.sun.java.help.search;
+
+import java.io.*;
+
+class StreamDecompressor extends Decompressor
+{
+  private InputStream _input;
+  
+  public StreamDecompressor(InputStream input) {
+    initReading(input);
+  }
+
+  public void initReading(InputStream input)
+  {
+    _input = input;
+    initReading();
+  }
+  
+  public int getNextByte() throws java.io.IOException {
+    return _input.read();
+  }
+
+  public static void main(String[] args)
+  {
+    try {
+      FileInputStream file = new FileInputStream(args[0]);
+      try {
+	int k1 = file.read();
+	long start = System.currentTimeMillis();
+	System.out.println("k1 = " + k1);
+	IntegerArray concepts = new IntegerArray();
+	StreamDecompressor documents = new StreamDecompressor(file);
+	try {
+	  documents.ascDecode(k1, concepts);
+	}
+	catch (Exception e) {
+	  System.err.println(e);
+	}
+	System.out.println("index1 = " + concepts.cardinality());
+	int k2 = file.read();
+	System.out.println("k2 = " + k2);
+	IntegerArray offs = new IntegerArray(concepts.cardinality());
+	StreamDecompressor offsets = new StreamDecompressor(file);
+	try {
+	  offsets.decode(k2, offs);
+	}
+	catch (Exception e) {
+	  System.err.println(e);
+	}
+	System.out.println("index2 = " + offs.cardinality());
+	System.out.println((System.currentTimeMillis() - start) + " msec");
+	file.close();
+      }
+      catch (IOException e) {
+	System.err.println(e);
+      }
+    }
+    catch (FileNotFoundException e) {
+      System.err.println(e);
+    }
+  }
+}
diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/TemporaryRAFFile.java b/jhMaster/JSearch/client/com/sun/java/help/search/TemporaryRAFFile.java
new file mode 100644
index 0000000000000000000000000000000000000000..ffce75a4f0ecb5bae6e6f646f5e646cdc9ac89b8
--- /dev/null
+++ b/jhMaster/JSearch/client/com/sun/java/help/search/TemporaryRAFFile.java
@@ -0,0 +1,128 @@
+/*
+ * @(#)TemporaryRAFFile.java	1.4 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @(#) TemporaryRAFFile.java 1.4 - last change made 10/30/06
+ */
+
+package com.sun.java.help.search;
+
+import java.io.IOException;
+
+/**
+ * This class can be used to read/write the contents of a RAF type files
+ * (i.e. DICT (Dictionary) & POSITIONS (Positions))
+ * file as part of JavaHelp Search Database. It uses RandamAccessFile for 
+ * quick access to dictionary blocks (DictBlock). 
+ * </p>
+ * Extension of this class serve include memory resident  or unwriteable  
+ * RAFFile.
+ *
+ * @author Roger D. Brinkley
+ * @author Eduardo Pelegri-Llopart
+ * @version	1.4	10/30/06
+ */
+
+import java.net.URL;
+import java.io.RandomAccessFile;
+import java.io.File;
+import java.io.IOException;
+import java.security.Permission;
+
+final public class TemporaryRAFFile extends RAFFile {
+
+    private RandomAccessFile raf;
+    private Permission permission;
+
+    // provides only read access.
+    public TemporaryRAFFile(File file, Permission permission) throws IOException{
+	debug("TemporaryRAFFile " + file);
+	raf = new RandomAccessFile(file, "r");
+	this.permission = permission;
+    }
+
+    public long length() throws IOException { 
+	// check permission
+	return raf.length();
+    }
+
+    public long getFilePointer() throws IOException {
+	// check permission
+	return raf.getFilePointer();
+    }
+
+    public void close() throws IOException {
+	// check permission
+	raf.close();
+    }
+
+    public void seek(long pos) throws IOException {
+	// check permission
+	raf.seek(pos);
+    }
+
+    public int readInt() throws IOException {
+	// check permission
+	return raf.readInt();
+    }
+
+    public int read() throws IOException {
+	// check permission
+	return raf.read();
+    }
+
+    public void readFully (byte b[]) throws IOException {
+	// check permission
+	raf.readFully(b);
+    }
+
+    public int read(byte[] b, int off, int len) throws IOException {
+	// check permission
+	return raf.read(b, off, len);
+    }
+  
+    public void writeInt(int v) throws IOException {
+	// check permission
+	raf.writeInt(v);
+    }
+
+    public void write(byte b[]) throws IOException {
+	// check permission
+	raf.write(b);
+    }
+
+    /**
+     * Debug code
+     */
+
+    private static final boolean debug = false;
+    private static void debug(String msg) {
+        if (debug) {
+            System.err.println("TemporaryRAFFile: "+msg);
+        }
+    }
+}
diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/Utilities.java b/jhMaster/JSearch/client/com/sun/java/help/search/Utilities.java
new file mode 100644
index 0000000000000000000000000000000000000000..f6d58a5878ef25288cd4d78c911804afc77a5b70
--- /dev/null
+++ b/jhMaster/JSearch/client/com/sun/java/help/search/Utilities.java
@@ -0,0 +1,60 @@
+/*
+ * @(#)Utilities.java	1.3 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ *	1.3 10/30/06
+ */
+
+package com.sun.java.help.search;
+
+import java.lang.reflect.Method;
+
+/**
+ *
+ * @version	1.3 10/30/06
+ * @author Roger D. Brinkley
+ */
+
+class Utilities
+{
+    public static String URLDecoder (String str) {
+	String returnStr = str;
+	try {
+	    Class klass = Class.forName("java.net.URLDecoder");
+	    Class types[] = {String.class};
+	    Method m = klass.getMethod("decode", types);
+	    
+	    if (m != null) {
+		Object args[] = {str};
+		returnStr = (String)m.invoke(null, args);
+	    }
+	} catch (Throwable t) {
+	    t.printStackTrace();
+	}
+	return returnStr;
+    }
+}
diff --git a/jhMaster/JSearch/client/com/sun/java/help/search/package.html b/jhMaster/JSearch/client/com/sun/java/help/search/package.html
new file mode 100644
index 0000000000000000000000000000000000000000..09fc77ecee0d1da7e3f5ccfb63e160413a0f4b22
--- /dev/null
+++ b/jhMaster/JSearch/client/com/sun/java/help/search/package.html
@@ -0,0 +1,56 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<!--
+
+  @(#)package.html 1.2 10/15/98
+
+  Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+  DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+  This code is free software; you can redistribute it and/or modify it
+  under the terms of the GNU General Public License version 2 only, as
+  published by the Free Software Foundation.  Sun designates this
+  particular file as subject to the "Classpath" exception as provided
+  by Sun in the LICENSE file that accompanied this code.
+
+  This code is distributed in the hope that it will be useful, but WITHOUT
+  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+  version 2 for more details (a copy is included in the LICENSE file that
+  accompanied this code).
+
+  You should have received a copy of the GNU General Public License version
+  2 along with this work; if not, write to the Free Software Foundation,
+  Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+  Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+  CA 95054 USA or visit www.sun.com if you need additional information or
+  have any questions.
+
+-->
+
+</head>
+<body bgcolor="white">
+
+Implementation classes for the default Search client using in the
+reference implementation of JavaHelp.
+
+<p>
+<em>Note:</em>We have not yet finalized the location for these classes.
+
+<!--
+<H2>Package Specification</H2>
+Link to updated API specification to be added here.
+-->
+
+<H2>Related Documentation</H2>
+
+<P>
+For overviews, tutorials, examples, guides, tool support,
+and other documentation,
+please see
+<A HREF="http://java.sun.com/products/javahelp/">the JavaHelp home page</A>
+
+  </body>
+</html>
diff --git a/jhMaster/JSearch/indexer/GNUmakefile b/jhMaster/JSearch/indexer/GNUmakefile
new file mode 100644
index 0000000000000000000000000000000000000000..503fdd603f230c02c9a2da6d5bb1a964a54c869e
--- /dev/null
+++ b/jhMaster/JSearch/indexer/GNUmakefile
@@ -0,0 +1,47 @@
+#
+# @(#)GNUmakefile	1.9 06/10/30
+# 
+# Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+# 
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.  Sun designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Sun in the LICENSE file that accompanied this code.
+# 
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+# 
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+# 
+# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+# CA 95054 USA or visit www.sun.com if you need additional information or
+# have any questions.
+#
+
+SOURCES := $(shell find . -name 'SCCS*' -prune -o -name '*Old*' -prune -o -name '*.java' -print)
+CLASSES = $(SOURCES:%.java=classes/%.class)
+
+RM=/bin/rm
+
+jar:	../lib/jsearch-indexer.jar
+
+../lib/jsearch-indexer.jar: $(CLASSES)
+	cd classes ; \
+	jar cf ../../lib/jsearch-indexer.jar com
+
+classes/%.class: %.java classes
+	export CLASSPATH ; CLASSPATH=../lib/jsearch-misc.jar:../lib/jsearch-client.jar:. ; \
+	javac -d classes $<
+
+classes:
+	mkdir classes
+
+clean:
+	$(RM) -rf classes
diff --git a/jhMaster/JSearch/indexer/com/sun/java/help/search/BtreeDictCompactor.java b/jhMaster/JSearch/indexer/com/sun/java/help/search/BtreeDictCompactor.java
new file mode 100644
index 0000000000000000000000000000000000000000..43b658a420505987b837bf7a39731d7ec6f47e67
--- /dev/null
+++ b/jhMaster/JSearch/indexer/com/sun/java/help/search/BtreeDictCompactor.java
@@ -0,0 +1,267 @@
+/*
+ * @(#)BtreeDictCompactor.java	1.9 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @date   5/1/98
+ * @author Jacek R. Ambroziak
+ * @group  Sun Microsystems Laboratories
+ */
+
+package com.sun.java.help.search;
+
+import java.net.URL;
+
+public class BtreeDictCompactor extends FullBtreeDict
+{
+  private CompactorDictBlock _currentLeaf;
+  private byte[]          _lastKey = new byte[MaxKeyLength];
+  private int             _lastKeyLength = 0;
+  private int             _limit;
+  private int             _nEntries = 0;
+  private int             _entry = 0;
+  
+  private int             _counter = 0;
+  private InternalBlockState _parent = null;
+  
+  private final class CompactorDictBlock extends FullDictBlock
+  {
+    private int restoreKey1(int entry, byte[] buffer)
+    {
+      int howMany = entryKeyLength(entry);
+      int where = entryCompression(entry);
+      int from = entryKey(entry);
+      while (howMany-- > 0)
+	buffer[where++] = data[from++];
+      return where;
+    }
+  
+    protected void doMap1(BtreeDictCompactor owner, BtreeDictCompactor target)
+      throws Exception
+    {
+      byte[] buffer = new byte[MaxKeyLength];
+      final int freeSpace = free();
+      int entry = firstEntry();
+      if (isLeaf)
+	while (entry < freeSpace) {
+	  target.store(buffer, restoreKey1(entry, buffer), entryID(entry));
+	  entry = nextEntry(entry);
+	}
+      else
+	{
+	  owner.lock(this);
+	  int entryIndex  = 0;
+	  while (entry < freeSpace) {
+	    owner.accessBlock1(getChildIdx(entryIndex)).doMap1(owner,target);
+	    target.store(buffer, restoreKey1(entry, buffer), entryID(entry));
+	    entry = nextEntry(entry);
+	    ++entryIndex;
+	  }
+	  owner.accessBlock1(getChildIdx(entryIndex)).doMap1(owner, target);
+	  owner.unlock(this);
+	}
+    }
+  } // end of internal class
+
+  private final class InternalBlockState
+  {
+    private CompactorDictBlock _block;
+    private byte[]             _lastKey = new byte[MaxKeyLength];
+    private int               _lastKeyLength;
+    private int             _entry;
+    private int             _nEntries;
+    private int             _limit;
+    private InternalBlockState _parent;
+  
+    public InternalBlockState(int leftChild)
+    {
+      debug("NEW ROOT " + _counter);
+      debug(params.toString());
+      params.setRoot(_counter);
+      _block = new CompactorDictBlock();
+      _block.isLeaf = false;
+      _block.setBlockNumber(_counter++);
+      init(leftChild);
+    }
+    
+    private void init(int leftChild)
+    {
+      _entry = _block.firstEntry();
+      _nEntries = 0;
+      _lastKeyLength = 0;
+      _limit = 4*(lastPtrIndex - 1);
+      _block.setChildIndex(0, leftChild);
+    }
+  
+    public void store(byte[] buffer, int keyLen, int id, int newBlock)
+    {
+      //      System.out.println(new String(buffer, 0, keyLen) + " " + id);
+      int cpr = 0;
+      while (cpr < _lastKeyLength && _lastKey[cpr] == buffer[cpr])
+	++cpr;
+      int needed = ENTHEADERLEN + keyLen - cpr;
+      if (_entry + needed <= _limit)
+	{
+	  _block.makeEntry(_entry, buffer, id, keyLen - cpr, cpr);
+	  _entry += needed;
+	  _nEntries++;
+	  _block.setChildIndex(_nEntries, newBlock);
+	  _limit -= 4;
+	  _lastKeyLength = keyLen;
+	  System.arraycopy(buffer, cpr, _lastKey, cpr, keyLen - cpr);
+	}
+      else
+	{
+	  debug("NEW: SPLIT INTERNAL");
+	  _block.setFree(_entry);
+	  _block.setNumberOfEntries(_nEntries);
+	  if (_parent == null)
+	    _parent = new InternalBlockState(_block.number);
+	  _parent.store(buffer, keyLen, id, newBlock(_block));
+	  init(newBlock);
+	}
+    }
+    
+    public void close() throws java.io.IOException
+    {
+      _block.setFree(_entry);
+      _block.setNumberOfEntries(_nEntries);
+      blockManager.writeBlock(_block);
+      if (_parent == null)
+	debug("root: " + _block.number);
+      else
+	_parent.close();
+    }
+  } // end of internal class
+
+  public BtreeDictCompactor(BtreeDictParameters params, boolean update)
+    throws Exception
+  {
+    init(params, update, new BlockFactory() {
+      public Block makeBlock() { return new CompactorDictBlock(); }
+    });
+    _currentLeaf = new CompactorDictBlock();
+    _currentLeaf.setBlockNumber(_counter++);
+    _limit = DATALEN - 2;
+    _entry = _currentLeaf.firstEntry();
+    this.params = params;
+  }
+
+  protected CompactorDictBlock accessBlock1(int index) throws Exception {
+    return (CompactorDictBlock)blockManager.accessBlock(index);
+  }
+  
+  public void store(byte[] buffer, int keyLen, int id)
+  {
+    //    System.out.println(new String(buffer, 0, keyLen));
+    if (id > 0)
+      {
+	int cpr = 0;
+	while (cpr < _lastKeyLength && _lastKey[cpr] == buffer[cpr])
+	  ++cpr;
+	int needed = ENTHEADERLEN + keyLen - cpr;
+	if (_entry + needed <= _limit)
+	  {
+	    _currentLeaf.makeEntry(_entry, buffer, id, keyLen - cpr, cpr);
+	    _entry += needed;
+	    _nEntries++;
+	    _lastKeyLength = keyLen;
+	    System.arraycopy(buffer, cpr, _lastKey, cpr, keyLen - cpr);
+	  }
+	else
+	  {
+	    _currentLeaf.setFree(_entry);
+	    _currentLeaf.setNumberOfEntries(_nEntries);
+	    if (_parent == null)
+	      _parent = new InternalBlockState(_currentLeaf.number);
+	    _parent.store(buffer, keyLen, id, newBlock(_currentLeaf));
+	    _entry = _currentLeaf.firstEntry();
+	    _nEntries = 0;
+	    _lastKeyLength = 0;
+	  }
+      }
+  }
+
+  private int newBlock(DictBlock block)
+  {
+    int number = _counter++;
+    try {
+      blockManager.writeBlock(block); // write out full
+      block.setBlockNumber(number); // recycle
+      blockManager.writeBlock(block); // reserve space for new
+    }
+    catch (java.io.IOException e) {
+      e.printStackTrace();
+    }
+    return number;
+  }
+
+  public void close() throws java.io.IOException
+  {
+    _currentLeaf.setFree(_entry);
+    _currentLeaf.setNumberOfEntries(_nEntries);
+    blockManager.writeBlock(_currentLeaf);
+    if (_parent == null)
+      debug("root: " + _currentLeaf.number);
+    else
+      _parent.close();
+    blockManager.close();
+  }
+
+  public void compact(BtreeDictParameters params) throws Exception
+  {
+    final BtreeDictCompactor target = new BtreeDictCompactor(params, true);
+    ((CompactorDictBlock)blockManager.accessBlock(root)).doMap1(this, target);
+    target.close();
+    blockManager.close();
+  }
+  
+  public static void main(String[] args)
+  {
+    try {
+      Schema schema = new Schema(null, args[0], false);
+      BtreeDictParameters params = new BtreeDictParameters(schema, "TMAP");
+      BtreeDictCompactor source = new BtreeDictCompactor(params, false);
+      URL url = new URL("file", "", args[1]);
+      BtreeDictParameters params2 = new BtreeDictParameters(url, 2048, 0, 24);
+      source.compact(params2);
+    }
+    catch (Exception e) {
+      System.err.println(e);
+      e.printStackTrace();
+    }
+  }
+  /**
+   * Debug code
+   */
+
+  private boolean debug=false;
+  private void debug(String msg) {
+    if (debug) {
+      System.err.println("BtreeDictCompactor: "+msg);
+    }
+  }
+}
diff --git a/jhMaster/JSearch/indexer/com/sun/java/help/search/ChangedCharSetException.java b/jhMaster/JSearch/indexer/com/sun/java/help/search/ChangedCharSetException.java
new file mode 100644
index 0000000000000000000000000000000000000000..31ddf166560087310366bca2a943466373bb13f2
--- /dev/null
+++ b/jhMaster/JSearch/indexer/com/sun/java/help/search/ChangedCharSetException.java
@@ -0,0 +1,61 @@
+/*
+ * @(#)ChangedCharSetException.java	1.6 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @(#) ChangedCharSetException.java 1.6 - last change made 10/30/06
+ */
+
+package com.sun.java.help.search;
+
+import java.io.IOException;
+
+/**
+ * ChangedCharSetException as the name indicates is an exception
+ * thrown when the charset is changed.
+ *
+ * @author Roger Brinkley
+ * 10/30/06 %V%
+ */
+public class ChangedCharSetException extends IOException {
+
+    String charSetSpec;
+    boolean charSetKey;
+
+    public ChangedCharSetException(String charSetSpec, boolean charSetKey) {
+	this.charSetSpec = charSetSpec;
+	this.charSetKey = charSetKey;
+    }
+
+    public String getCharSetSpec() {
+	return charSetSpec;
+    }
+
+    public boolean keyEqualsCharSet() {
+	return charSetKey;
+    }
+
+}
diff --git a/jhMaster/JSearch/indexer/com/sun/java/help/search/DefaultIndexBuilder.java b/jhMaster/JSearch/indexer/com/sun/java/help/search/DefaultIndexBuilder.java
new file mode 100644
index 0000000000000000000000000000000000000000..04b978c5f965f795797024331d54fffa6d3c47c1
--- /dev/null
+++ b/jhMaster/JSearch/indexer/com/sun/java/help/search/DefaultIndexBuilder.java
@@ -0,0 +1,243 @@
+/*
+ * @(#)DefaultIndexBuilder.java	1.23 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @date   3/13/98
+ * @author Jacek R. Ambroziak
+ * @group  Sun Microsystems Laboratories
+ */
+
+package com.sun.java.help.search;
+
+import java.net.URL;
+import java.io.*;
+import java.util.Hashtable;
+import java.util.Enumeration;
+import javax.help.search.IndexBuilder;
+
+public class DefaultIndexBuilder extends IndexBuilder
+{
+  private static int InitSize = 4096;
+  private FullBtreeDict dict;
+  protected Hashtable cache = new Hashtable(15000);
+  private DocumentCompressor compr;
+  private int free = 0;
+  private int size = InitSize;
+  private ConceptLocation[] locations = new ConceptLocation[size];
+  private int freeID;
+  private int currentDocID = 0;
+  private Schema _schema;
+  private BtreeDictParameters _tmapParams;
+  private int _title = 0;
+
+  public DefaultIndexBuilder(String indexDir) throws Exception
+  {
+    super (indexDir);
+    // temporary code to disable incremental updates
+    removeExistingFiles(indexDir);
+    _schema = new Schema(null, indexDir, true);
+    _tmapParams = new BtreeDictParameters(_schema, "TMAP");
+    if (_tmapParams.readState() == false)
+      {
+	_tmapParams.setBlockSize(2048);
+	_tmapParams.setRoot(0);
+	_tmapParams.setFreeID(1);
+      }
+    
+    URL url = new URL("file", "", indexDir);
+    /*
+    try {
+      params = BtreeDictParameters.read(indexDir, null);
+    } catch (java.io.FileNotFoundException e) {
+      params = BtreeDictParameters.create(url);
+    }
+    */
+    dict = new FullBtreeDict(_tmapParams, true);
+    freeID = _tmapParams.getFreeID();
+    compr = new DocumentCompressor(url);
+  }
+
+    // temporary until Jacek incorporates stop words into IndexBuilder
+    private Hashtable tmpstopWords = new Hashtable();
+
+    public void storeStopWords(Enumeration stopWords) {
+	for (; stopWords.hasMoreElements() ;) {
+	    String word = (String) stopWords.nextElement();
+	    // temporarily keep the list here until Jacek finishes adding
+	    // stop words to indexes
+	    tmpstopWords.put(word, word);
+	}
+    }
+
+    public Enumeration getStopWords() {
+	// For now the stop words are not stored in the index
+	// Jacek will change this when he supports stop words in indexes
+	return null;
+    }
+
+    // temporary code until Jacek provides support for stop words in indexes
+    private boolean isStopWord(String word) {
+	return tmpstopWords.get(word) != null;
+    }
+
+  public void close() throws Exception
+  {
+    dict.close(freeID);
+    _tmapParams.setFreeID(freeID);
+    _tmapParams.updateSchema();
+    
+    debug("compacting...");
+    BtreeDictCompactor source = new BtreeDictCompactor(_tmapParams, false);
+    URL url = new URL("file", "", indexDir + "compacted");
+    BtreeDictParameters params =
+      new BtreeDictParameters(url, _tmapParams.getBlockSize(), 0, freeID);
+    source.compact(params);
+    URL tmapURL = new URL("file", "", indexDir + "TMAP");
+    File tmap = new File(Utilities.URLDecoder(tmapURL.getFile()));
+    tmap.delete();
+    File compacted = new File(Utilities.URLDecoder(url.getFile()));
+    compacted.renameTo(tmap);
+    _tmapParams.setRoot(params.getRootPosition());
+    _tmapParams.updateSchema();
+    
+    debug("freeID is " + freeID);
+    compr.close(indexDir + "OFFSETS");
+    debug("inverting index");
+    DocumentLists.invert(indexDir);
+    _schema.save();
+  }
+
+  public void openDocument(String name) throws Exception
+  {
+    if (currentDocID != 0) {
+      throw new Exception("document already open");
+    }
+    currentDocID = intern(name);
+  }
+  
+  public void closeDocument() throws Exception
+  {
+    if (currentDocID == 0) {
+      throw new Exception("no document open");
+    }
+    compr.compress(currentDocID, _title, locations, free, null, 0);
+    free = 0;
+    currentDocID = 0;		// state: nothing open
+    _title = 0;
+  }
+
+  public void storeLocation(String text, int position) throws Exception
+  {
+    // next line is temporary until Jacek provides support for stop words in
+    // indexes
+    if (isStopWord(text)) return;
+    if (free == size) {
+      ConceptLocation[] newArray = new ConceptLocation[size *= 2];
+      System.arraycopy(locations, 0, newArray, 0, free);
+      locations = newArray;
+    }
+    locations[free++] = new ConceptLocation(intern(text),
+					    position,
+					    position + text.length());
+  }
+
+  public void storeTitle(String title) throws Exception
+  {
+    _title = intern(title);
+  }
+
+  private int intern(String name) throws Exception
+  {
+    Integer cached = (Integer)cache.get(name);
+    if (cached != null)
+      return cached.intValue();
+    else
+      {
+	int id = dict.fetch(name);
+	if (id == 0) {
+	  dict.store(name, id = freeID++);
+	}
+	cache.put(name, new Integer(id));
+	return id;
+      }
+  }
+
+    /** 
+     * Temporary code to remove existing files
+     * remove when updates actually works
+     */
+    private void removeExistingFiles(String indexDir) {
+	File test = new File(indexDir);	
+	try {
+	    if (test.exists()) {
+		try {
+		    File tmap = new File(test, "TMAP");
+		    tmap.delete();
+		} catch (java.lang.NullPointerException te) {
+		}
+		try {
+		    File docs = new File(test, "DOCS");
+		    docs.delete();
+		} catch (java.lang.NullPointerException de) {
+		}
+		try {
+		    File docstab = new File(test, "DOCS.TAB");
+		    docstab.delete();
+		} catch (java.lang.NullPointerException dte) {
+		}
+		try {
+		    File offsets = new File(test, "OFFSETS");
+		    offsets.delete();
+		} catch (java.lang.NullPointerException oe) {
+		}
+		try {
+		    File positions = new File(test, "POSITIONS");
+		    positions.delete();
+		} catch (java.lang.NullPointerException pe) {
+		}
+		try {
+		    File schema = new File(test, "SCHEMA");
+		    schema.delete();
+		} catch (java.lang.NullPointerException se) {
+		}
+	    }
+	} catch (java.lang.SecurityException e) {
+	}
+	
+    }
+
+  /**
+   * Debug code
+   */
+
+  private boolean debug = false;
+  private void debug(String msg) {
+    if (debug) {
+      System.err.println("DefaultIndexBuilder: "+msg);
+    }
+  }
+}
diff --git a/jhMaster/JSearch/indexer/com/sun/java/help/search/DefaultIndexerKit.java b/jhMaster/JSearch/indexer/com/sun/java/help/search/DefaultIndexerKit.java
new file mode 100644
index 0000000000000000000000000000000000000000..d5690952f4bdca2677ee25429a3b7632d75782ca
--- /dev/null
+++ b/jhMaster/JSearch/indexer/com/sun/java/help/search/DefaultIndexerKit.java
@@ -0,0 +1,188 @@
+/*
+ * @(#)DefaultIndexerKit.java	1.17 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @(#) DefaultIndexerKit.java 1.17 - last change made 10/30/06
+ */
+
+package com.sun.java.help.search;
+
+import java.io.*;
+import java.util.Locale;
+import java.text.*;
+import javax.help.search.IndexerKit;
+import javax.help.search.IndexBuilder;
+import javax.help.search.ConfigFile;
+
+/**
+ * This is the set of things needed by an indexing object
+ * to be a reasonably functioning indexer for some <em>type</em>
+ * of text document.  This implementation provides a default
+ * implementation which treats text as plain text 
+ *
+ * @author  Roger D. Brinkley
+ * @version %I	%G
+ */
+public class DefaultIndexerKit extends IndexerKit {
+
+    protected boolean documentStarted;
+
+
+    public DefaultIndexerKit() {
+	locale = Locale.getDefault();
+    }
+
+    /**
+     * Creates a copy of the indexer kit.  This
+     * allows an implementation to serve as a prototype
+     * for others, so that they can be quickly created.
+     *
+     * @return the copy
+     */
+    public Object clone() {
+        return new DefaultIndexerKit();
+    }
+
+    /**
+     * Gets the MIME type of the data that this
+     * kit represents support for.  The default
+     * is <code>text/plain</code>.
+     *
+     * @return the type
+     */
+    public String getContentType() {
+        return "";
+    }
+
+    /**
+     * Inserts content from the given stream, which will be 
+     * treated as plain text.
+     * 
+     * @param in  The stream to read from
+     * @param file The file name being parsed
+     * @param ignoreCharset Ignore the CharacterSet when parsing
+     * @param builder The IndexBuilder for the full text insertion.
+     * @param config The indexer configuration information
+     * @exception IOException on any I/O error
+     */
+    public void parse(Reader in, String file, boolean ignoreCharset,
+		      IndexBuilder builder, 
+		      ConfigFile config) throws IOException 
+    {
+	debug ("parsing " + file); 
+	// Do nothing in the default implementation
+    }
+
+    public int parseIntoTokens (String source, int pos) {
+	BreakIterator boundary;
+	int start;
+	String word;
+	int currentPos = pos;
+
+	try {
+	    boundary = BreakIterator.getWordInstance(locale);
+	    boundary.setText(source);
+	    start = boundary.first();
+	    for (int end = boundary.next();
+		 end != BreakIterator.DONE;
+		 start = end, end = boundary.next()) {
+		word = new String(source.substring(start,end));
+		word = word.trim();
+		word = word.toLowerCase(locale);
+		if (word.length() > 1) {
+		    storeToken(word, currentPos + start);
+		} else if (word.length() == 1) {
+		    int charType = Character.getType(word.charAt(0));
+		    if ((charType == Character.DECIMAL_DIGIT_NUMBER) || 
+			(charType == Character.LETTER_NUMBER) || 
+			(charType == Character.LOWERCASE_LETTER) || 
+			(charType == Character.OTHER_LETTER) || 
+			(charType == Character.OTHER_NUMBER) || 
+			(charType == Character.TITLECASE_LETTER) || 
+			(charType == Character.UNASSIGNED) || 
+			(charType == Character.UPPERCASE_LETTER)) {
+			storeToken (word, currentPos + start);
+		    }
+		}
+	    }
+	    currentPos += source.length();
+	}
+	catch (Exception e) {
+	    e.printStackTrace();
+	}
+	return currentPos;
+    }
+
+    protected void startStoreDocument (String file) throws Exception {
+	if ((config == null) || (builder == null)) {
+	    throw new Exception("ConfigFile and/or IndexBuilder not set");
+	}
+	builder.openDocument(config.getURLString(file));
+    }
+
+    protected void endStoreDocument () throws Exception {
+	if ((config == null) || (builder == null)) {
+	    throw new Exception("ConfigFile and/or IndexBuilder not set");
+	}
+	builder.closeDocument();
+    }
+
+    protected void storeToken (String token, int pos) throws Exception {
+	if ((config == null) || (builder == null)) {
+	    throw new Exception("ConfigFile and/or IndexBuilder not set");
+	}
+	if (!documentStarted) {
+	    try {
+		startStoreDocument(file);
+		documentStarted = true;
+	    } catch (Exception e) {
+		if (debugFlag) e.printStackTrace();
+		throw new IOException("Can't store Document");
+	    }
+	}
+	builder.storeLocation(token, pos);
+    }
+
+    protected void storeTitle (String title) throws Exception {
+	if ((config == null) || (builder == null)) {
+	    throw new Exception("ConfigFile and/or IndexBuilder not set");
+	}
+	builder.storeTitle(title);
+    }
+
+
+    /**
+     * Debug code
+     */
+
+    private boolean debugFlag=false;
+    private void debug(String msg) {
+        if (debugFlag) {
+            System.err.println("DefaultIndexKit: "+msg);
+        }
+    }
+}
diff --git a/jhMaster/JSearch/indexer/com/sun/java/help/search/DocumentLists.java b/jhMaster/JSearch/indexer/com/sun/java/help/search/DocumentLists.java
new file mode 100644
index 0000000000000000000000000000000000000000..69b539fbdbbafb3e05dbb3274de11b1ece4e7a17
--- /dev/null
+++ b/jhMaster/JSearch/indexer/com/sun/java/help/search/DocumentLists.java
@@ -0,0 +1,294 @@
+/*
+ * @(#)DocumentLists.java	1.7 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @date   3/10/98
+ * @author Jacek R. Ambroziak
+ * @group  Sun Microsystems Laboratories
+ */
+
+package com.sun.java.help.search;
+
+import java.io.*;
+
+class DocumentLists
+{
+  private static final int RANGE = 1024;
+  private static final int NConcepts = 16;
+  private static final int K = 3;
+  
+  private final IntegerArray[] _arrays = new IntegerArray[RANGE];
+  private int _minConcept = 0;
+  private int _limit = RANGE;
+  private final IntegerArray _concepts = new IntegerArray();
+  private final IntegerArray _offsets = new IntegerArray();
+  private final Compressor _compr = new Compressor();
+  private final IntegerArray _diffs = new IntegerArray();
+  private final ByteArrayDecompressor _decmp =
+  new ByteArrayDecompressor(null, 0);
+  private DataOutputStream _mainFile;
+  // heap
+  private int          _heapSize = 0;
+  private MicroIndex[] _heap;
+  
+  private class MicroIndex
+  {
+    private int _currentRange;
+    private final int _documentNumber;
+    private int[] _concepts = new int[NConcepts + 1];
+    private short _group;
+    private short _ix;
+    private IntegerArray _kTable = new IntegerArray();
+    private IntegerArray _offsets = new IntegerArray();
+    private IntegerArray _maxConcepts = new IntegerArray();
+    private byte[] _data;
+    private int _base;
+    private int _limit;
+    private int _nc;
+
+    public MicroIndex(int documentNumber, byte[] positions, int index)
+      throws Exception
+    {
+      _documentNumber = documentNumber;
+      _data = positions;
+      _base = index;
+      openDocumentIndex();
+    }
+  
+    public boolean smallerThan(MicroIndex other)
+    {
+      return _currentRange < other._currentRange ||
+	_currentRange == other._currentRange &&
+	_documentNumber < other._documentNumber;
+    }
+
+    private boolean next() throws Exception
+    {
+      if (_group <= _limit)
+	{
+	  int shift, index;
+	  if (_group > 0)
+	    {
+	      index = _base + _offsets.at(_group - 1);
+	      shift = _maxConcepts.at(_group - 1);
+	    }
+	  else
+	    {
+	      index = _base;
+	      shift = 0;
+	    }
+	  _decmp.initReading(_data, index);
+	  _nc = _decmp.ascendingDecode(_kTable.at(_group*2), shift, _concepts);
+	  if (_group < _limit)
+	    _concepts[_nc++] = _maxConcepts.at(_group);
+	  _currentRange = _concepts[_ix = 0]/RANGE;
+	  _group++;
+	  return true;
+	}
+      else
+	return false;
+    }
+  
+    private void openDocumentIndex() throws Exception
+    {
+      int kk = _data[_base] & 0xFF;
+      switch (kk >> 6)		// get type
+	{
+	case 0:			// single group, no extents
+	  _decmp.initReading(_data, _base += 2);
+	  _nc = _decmp.ascendingDecode(kk & 0x3F, 0, _concepts);
+	  _currentRange = _concepts[_ix = 0]/RANGE;
+	  _limit = 0;
+	  _group = 1;
+	  break;
+      
+	case 2:			// multi group, no extents
+	  _decmp.initReading(_data, _base + 1);
+	  _decmp.decode(kk & 0x3F, _kTable);
+	  _decmp.ascDecode(_kTable.popLast(), _offsets);
+	  _decmp.ascDecode(_kTable.popLast(), _maxConcepts);
+	  _base += 1 + _decmp.bytesRead();
+	  _limit = _maxConcepts.cardinality();
+	  _group = 0;
+	  next();
+	  break;
+      
+	case 1:			// single group, extents
+	case 3:			// multi group, extents
+	  System.err.println("extents not yet implemented\n");
+	  break;
+	}
+    }
+  
+    public boolean process(DocumentLists lists) throws Exception
+    {
+      boolean firstTime = true;
+      while (true)
+	{
+	  short stop = lists.process(_documentNumber, _concepts, _nc, _ix,
+				     firstTime);
+	  if (stop < _nc)
+	    {
+	      _currentRange = _concepts[_ix = stop]/RANGE;
+	      return true;
+	    }
+	  else if (next())
+	    firstTime = false;
+	  else
+	    return false;
+	}
+    }
+  }
+
+  private DocumentLists(String indexDir) throws Exception
+  {
+    for (int i = 0; i < RANGE; i++)
+      _arrays[i] = new IntegerArray();
+    _mainFile = new DataOutputStream
+      (new BufferedOutputStream
+       (new FileOutputStream(indexDir + "DOCS")));
+    // main work
+    InputStream file =
+      new BufferedInputStream(new FileInputStream(indexDir + "OFFSETS"));
+    int k1 = file.read();
+    IntegerArray array = new IntegerArray(4096);
+    StreamDecompressor documents = new StreamDecompressor(file);
+    documents.ascDecode(k1, array);
+    int k2 = file.read();
+    IntegerArray offsetArray = new IntegerArray(array.cardinality() + 1);
+    StreamDecompressor offsets = new StreamDecompressor(file);
+    offsets.ascDecode(k2, offsetArray);
+    file.close();
+    File listsFile = new File(indexDir + "POSITIONS");
+    byte[] positions = new byte[(int)listsFile.length()];
+    FileInputStream in = new FileInputStream(listsFile);
+    in.read(positions);
+    in.close();
+    // build heap
+    _heap = new MicroIndex[_heapSize = array.cardinality()];
+    for (int i = 0; i < array.cardinality(); i++)
+      _heap[i] = new MicroIndex(i, positions, offsetArray.at(i));
+    debug(array.cardinality() + " documents");
+    for (int i = _heapSize/2; i >= 0; i--)
+      heapify(i);
+    // process till exhausted
+    while (true)
+      if (_heap[0].process(this))
+	heapify(0);
+      else if (_heapSize > 1)
+	{
+	  _heap[0] = _heap[--_heapSize];
+	  heapify(0);
+	}
+      else
+	break;
+    // closing
+    flush();
+    _mainFile.close();
+    // compress index file
+    DataOutputStream indexFile = new DataOutputStream
+      (new BufferedOutputStream
+       (new FileOutputStream(indexDir + "DOCS.TAB")));
+    indexFile.write(_compr.compressAscending(_concepts)); // write k
+    _compr.write(indexFile);
+    _compr.clear();
+    indexFile.write(_compr.minimize(_offsets, K)); // write k
+    _compr.write(indexFile);
+    indexFile.close();
+  }
+
+  public short process(int documentNumber, int[] concepts, int n, short start,
+		       boolean firstTime)
+    throws IOException
+  {
+    if (firstTime && concepts[start] >= _limit)
+      flush();
+    concepts[n] = _limit; // sentinel
+    while (concepts[start] < _limit)
+      _arrays[concepts[start++] - _minConcept].add(documentNumber);
+    return start;
+  }
+  
+  private void heapify(int i)
+  {
+    int r = (i + 1) << 1, l = r - 1;
+    int smallest = l < _heapSize && _heap[l].smallerThan(_heap[i]) ? l : i;
+    if (r < _heapSize && _heap[r].smallerThan(_heap[smallest]))
+      smallest = r;
+    if (smallest != i)
+      {
+	MicroIndex temp = _heap[smallest];
+	_heap[smallest] = _heap[i];
+	_heap[i] = temp;
+	heapify(smallest);
+      }
+  }
+  
+  private void flush() throws IOException
+  {
+    for (int i = 0; i < RANGE; i++)
+      if (_arrays[i].cardinality() > 0)
+	{
+	  _arrays[i].toDifferences(_diffs);
+	  _mainFile.write(_compr.minimize(_diffs, K)); // write k
+	  _offsets.add(_compr.byteCount() + 1);
+	  _compr.write(_mainFile);
+	  _concepts.add(_minConcept + i);
+	  _arrays[i].clear();
+	  _diffs.clear();
+	  _compr.clear();
+	}
+    _limit += RANGE;
+    _minConcept += RANGE;
+  }
+
+  public static void invert(String indexDir) throws Exception {
+    new DocumentLists(indexDir);
+  }
+
+  public static void main(String[] args)
+  {
+    String indexDir = args[0];
+    try {
+      new DocumentLists(indexDir);
+    }
+    catch (Exception e) {
+      e.printStackTrace();
+    }
+  }
+    /**
+     * Debug code
+     */
+
+    private boolean debug=false;
+    private void debug(String msg) {
+        if (debug) {
+            System.err.println("DocumentLists: "+msg);
+        }
+    }
+
+}
diff --git a/jhMaster/JSearch/indexer/com/sun/java/help/search/FullBtreeDict.java b/jhMaster/JSearch/indexer/com/sun/java/help/search/FullBtreeDict.java
new file mode 100644
index 0000000000000000000000000000000000000000..15de5da732969248e7936c9587c5bf63c6883275
--- /dev/null
+++ b/jhMaster/JSearch/indexer/com/sun/java/help/search/FullBtreeDict.java
@@ -0,0 +1,475 @@
+/*
+ * @(#)FullBtreeDict.java	1.15 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @date   2/20/98
+ * @author Jacek R. Ambroziak
+ * @group  Sun Microsystems Laboratories
+ */
+
+package com.sun.java.help.search;
+
+import java.io.*;		// debugging in main
+import java.util.*;		// debugging in main
+
+public class FullBtreeDict extends BtreeDict
+{
+  protected BtreeDictParameters params;
+  private boolean update = false;
+  
+  private final class Entry
+  {
+    public byte[] key;
+    public int    id;
+    public int    block = -1;
+  
+    public Entry(byte[] key, int length, int id)
+    {
+      this.key = new byte[length + 1];
+      System.arraycopy(key, 0, this.key, 0, length);
+      this.key[length] = 0;
+      this.id = id;
+    }
+  
+    public boolean smallerThan(Entry other)
+    {
+      for (int i = 0; i < Math.min(key.length, other.key.length); i++)
+	if (key[i] != other.key[i])
+	  return (key[i]&0xFF) < (other.key[i]&0xFF);
+      return false;
+    }
+  }
+  // end of internal class
+  
+  protected class FullDictBlock extends DictBlock
+  {
+    public void setFree(int free)
+    {
+      this.free = free - firstEntry();
+      this.data[free] = this.data[free + 1] = 0; // sentinel
+    }
+  
+    public void setNumberOfEntries(int n) {
+      setIntegerAt(0, n);
+    }
+
+    protected void setChildIndex(int index, int value) {
+      setIntegerAt(4*(lastPtrIndex - index + 1), value);
+    }
+  
+    public void setEntryID(int i, int id) {
+      setIntegerAt(i + 2, id);
+    }
+  
+    // finds the place and context
+    private boolean insert(Entry entry)
+    {
+      byte[] inkey = entry.key;
+      final int inputKeyLen = inkey.length - 1;
+      final int freeSpace   = free();
+      int entryPtr    = firstEntry();
+      int nCharsEqual = 0;
+      int prevNCEqual = 0;
+      int compression = 0;
+
+      for (int entryIndex = 0;;)
+	{
+	  if (entryPtr == freeSpace)
+	    return insert(entry, entryPtr, nCharsEqual, 0, numberOfEntries());
+	  else if (compression == nCharsEqual)
+	    {
+	      int keyLen = entryKeyLength(entryPtr);
+	      int keyPtr = entryKey(entryPtr), i;
+	      prevNCEqual = nCharsEqual;
+	      for (i = 0;
+		   i < keyLen && inkey[nCharsEqual] == data[keyPtr + i];
+		   i++)
+		++nCharsEqual;
+	      if (i == keyLen)
+		{
+		  if (nCharsEqual == inputKeyLen)
+		    {
+		      setEntryID(entryPtr, entry.id);
+		      return true;
+		    }
+		}
+	      else if ((inkey[nCharsEqual]&0xFF) < (data[keyPtr + i]&0xFF))
+		return insert(entry, entryPtr, prevNCEqual, nCharsEqual,
+			      entryIndex);
+	    }
+	  else if (compression < nCharsEqual) // compression dropped
+	    return insert(entry, entryPtr, nCharsEqual, compression,
+			  entryPtr == freeSpace
+			  ? numberOfEntries() : entryIndex);
+	  do {
+	    entryPtr = nextEntry(entryPtr);
+	    ++entryIndex;
+	  }
+	  while (entryCompression(entryPtr) > nCharsEqual);
+	  compression = entryCompression(entryPtr);
+	}
+    }
+    
+    public void makeEntry(int entry, byte[] key, int id, int length, int compr)
+    {
+      data[entry]     = (byte) length;
+      data[entry + 1] = (byte) compr;
+      setEntryID(entry, id);
+      System.arraycopy(key, compr, data, entryKey(entry), length);
+    }
+
+    private boolean insert(Entry ent, final int entryPtr,
+			   final int compr1, final int compr2,
+			   final int index)
+    {
+      final byte[] key = ent.key;
+      final int keyLen = key.length - 1 - compr1;
+      final int freeSpace = free();
+      // calculate how much space is needed to add the new entry
+      // first, how many bytes are needed for just the new entry
+      final int demand = ENTHEADERLEN + keyLen;
+      // adding an entry can increase compression in the following entry
+      
+      int increase = 0;
+      if (entryPtr < freeSpace)
+	if (entryCompression(entryPtr) < compr2)
+	  increase = compr2 - entryCompression(entryPtr);
+      /*
+      System.err.println("key " + key);
+      System.err.println("entryPtr " + entryPtr);
+      System.err.println("compr1 " + compr1);
+      System.err.println("compr2 " + compr2);
+      System.err.println("index " + index);
+      System.err.println("demand " + demand);
+      System.err.println("increase " + increase);
+      */
+      // check if enough space is available
+      int limit = isLeaf ? DATALEN-2 : 4*(lastPtrIndex-numberOfEntries()-1);
+    
+      if (freeSpace + demand - increase <= limit)// 2 for sentinel
+	{
+	  if (entryPtr < freeSpace)
+	    {
+	      // need to shift extant entries forward
+	      final int toMove = increase > 0
+		? entryPtr + ENTHEADERLEN + increase
+		: entryPtr;
+	      // move entries
+	      System.arraycopy(data, toMove,
+			       data, toMove + demand - increase,
+			       freeSpace - toMove);
+	      if (increase > 0)
+		{
+		  // update header
+		  data[entryPtr]     -= increase;
+		  data[entryPtr + 1] += increase;
+		  // shift header
+		  System.arraycopy(data, entryPtr,
+				   data, entryPtr + demand, ENTHEADERLEN);
+		}
+	    }
+	  // now write the new entry in the space made above
+	  makeEntry(entryPtr, key, ent.id, keyLen, compr1);
+	  if (isLeaf == false)
+	    {
+	      int from = 4*(lastPtrIndex - numberOfEntries() + 1);
+	      System.arraycopy(data, from, data, from - 4,
+			       4*(numberOfEntries() - index));
+	      setChildIndex(index + 1, ent.block);
+	    }
+	  setFree(freeSpace + demand - increase);
+	  setNumberOfEntries(numberOfEntries() + 1);
+	  
+
+	  /*
+	  System.err.println("------------list--------------");
+      byte[] buffer = new byte[MaxKeyLength];
+      final int freeSpace2 = free();
+      int entryPtr2 = firstEntry();
+      while (entryPtr2 < freeSpace2)
+	{
+	  System.err.println(entryPtr2);
+	  System.err.println(entryKeyLength(entryPtr2));
+	  System.err.println(entryCompression(entryPtr2));
+	  System.err.println(new String(data,
+					entryKey(entryPtr2),
+					entryKeyLength(entryPtr2)));
+	  System.err.println(restoreKey(entryPtr2, buffer)+" "+
+			     entryID(entryPtr2));
+	  entryPtr2 = nextEntry(entryPtr2);
+	}
+      System.err.println("------------end--------------");
+      */
+
+	  
+	  return true;
+	}
+      else
+	return false;
+    }
+  
+    public int insertInternal(Entry entry)
+    {
+      byte[] inkey    = entry.key;
+      final int inputKeyLen = inkey.length - 1;
+      int entryPtr    = firstEntry();
+      final int freeSpace   = free();
+      int nCharsEqual = 0;
+      int compression = 0;
+
+      for (int entryIndex = 0;;)
+	{
+	  if (entryPtr == freeSpace)
+	    return numberOfEntries();
+	  else if (compression == nCharsEqual)
+	    {
+	      int i;
+	      int keyLen = entryKeyLength(entryPtr);
+	      int keyPtr = entryKey(entryPtr);
+	      for (i = 0;
+		   i < keyLen && inkey[nCharsEqual] == data[keyPtr + i];
+		   i++)
+		++nCharsEqual;
+	      if (i == keyLen)
+		{
+		  if (nCharsEqual == inputKeyLen)
+		    {
+		      setEntryID(entryPtr, entry.id);
+		      return -1;
+		    }
+		}
+	      else if ((inkey[nCharsEqual]&0xFF) < (data[keyPtr + i]&0xFF))
+		return entryIndex;
+	    }
+	  else if (compression < nCharsEqual) // compression dropped
+	    return entryPtr >= freeSpace ? numberOfEntries() : entryIndex;
+    
+	  do {
+	    entryPtr = nextEntry(entryPtr);
+	    ++entryIndex;
+	  }
+	  while (entryCompression(entryPtr) > nCharsEqual);
+	  compression = entryCompression(entryPtr);
+	}
+    }
+  
+    private Entry split(FullDictBlock newbl)
+    {
+      byte[] buffer = new byte[MaxKeyLength];
+      int freeSpace = free();
+      int half      = freeSpace/2;
+      int index     = 0;		// of middle entry
+      newbl.isLeaf = isLeaf;
+      int ent;
+      for (ent = firstEntry(); ent < half; ent = nextEntry(ent))
+	{
+	  restoreKeyInBuffer(ent, buffer);
+	  ++index;
+	}
+      final int entriesToMove = numberOfEntries() - index - 1;
+      // middle entry
+      restoreKeyInBuffer(ent, buffer);
+      int len = entryKeyLength(ent) + entryCompression(ent);
+      Entry result = new Entry(buffer, len, entryID(ent));
+      result.block = newbl.number;
+      int newFree = ent;
+      // rest goes to the new block
+      ent = nextEntry(ent);
+      restoreKeyInBuffer(ent, buffer);
+      len = entryKeyLength(ent) + entryCompression(ent);
+      int nptr = firstEntry();
+      newbl.makeEntry(nptr, buffer, entryID(ent), len, 0);
+      ent = nextEntry(ent);
+      System.arraycopy(data, ent,
+		       newbl.data, newbl.nextEntry(nptr), freeSpace - ent);
+      newbl.setNumberOfEntries(entriesToMove);
+      newbl.setFree(newbl.nextEntry(nptr) + freeSpace - ent);
+      if (isLeaf == false)	// need to split pointers
+	{
+	  int from = 4*(lastPtrIndex - numberOfEntries() + 1);
+	  System.arraycopy(data, from,
+			   newbl.data, from + 4*(index + 1),
+			   4*(entriesToMove + 1));
+	}
+      // this entry will end here
+      setFree(newFree);
+      setNumberOfEntries(index);
+      return result;
+      //!!!remember updating ID -> string association
+    }
+  
+    public void initInternal(int leftBlock, Entry entry)
+    {
+      isLeaf = false;
+      setNumberOfEntries(1);
+      setChildIndex(0, leftBlock);
+      setChildIndex(1, entry.block);
+      final int ent = firstEntry();
+      makeEntry(ent, entry.key, entry.id, entry.key.length - 1, 0);
+      setFree(nextEntry(ent));
+    }
+  }
+  // end of internal class
+
+  protected  FullBtreeDict() {/*empty*/}
+
+  public FullBtreeDict(BtreeDictParameters params, boolean update)
+    throws Exception
+  {
+    init(params, update, new BlockFactory() {
+      public Block makeBlock() { return new FullDictBlock(); }
+    });
+    blocks = new int[300000];	// !!!
+    this.params = params;
+    this.update = update;
+  }
+
+  public void close(int freeID) throws Exception
+  {
+    params.setFreeID(freeID);
+    if (update)
+      params.updateSchema();
+    super.close();
+  }
+
+  public void store(String key, int id) throws Exception
+  {
+    //    System.err.println("storing "+key+" id "+id);
+    byte[] bytes = key.getBytes("UTF8");
+    Entry entry = insert((FullDictBlock)accessBlock(root),
+			 new Entry(bytes, bytes.length, id));
+    if (entry != null)
+      {
+	// new root; writing to params needed
+	FullDictBlock nbl = getNewBlock();
+	nbl.initInternal(root, entry);
+	blocks[entry.id] = root = nbl.number;
+	params.setRoot(root);
+      }
+  }
+  
+  private void setModified(Block bl) {
+    blockManager.setModified(bl.number);
+  }
+  
+  private FullDictBlock getNewBlock() throws Exception
+  {
+    FullDictBlock nbl = (FullDictBlock)blockManager.getNewBlock();
+    setModified(nbl);
+    return nbl;
+  }
+
+  /*
+    delegation to powerful primitives at the FullDictBlock level lets us
+    express the insertion algorithm very succintly here
+    */
+
+  private Entry insert(FullDictBlock bl, Entry ent) throws Exception
+  {
+    if (bl.isLeaf)
+      return insertHere(bl, ent);
+    else
+      {
+	int index = bl.insertInternal(ent);
+	if (index != -1)
+	  try {
+	    lock(bl);
+	    ent = insert((FullDictBlock)child(bl, index), ent);
+	    return ent == null ? null : insertHere(bl, ent);
+	  }
+	finally {
+	  unlock(bl);
+	}
+	else
+	  return null;
+      }
+  }
+
+  private Entry insertHere(FullDictBlock bl, Entry ent) throws Exception
+  {
+    setModified(bl);		// to be modified in any case 
+    if (bl.insert(ent))
+      return null;
+    else
+      {
+	FullDictBlock nbl = getNewBlock();
+	Entry middle = bl.split(nbl);
+	nbl.setBlockNumbers(blocks);
+	if ((middle.smallerThan(ent) ? nbl : bl).insert(ent) == false)
+	  throw new Exception("entry didn't fit into a freshly split block");
+	return middle;
+      }
+  }
+  
+  public static void main(String[] args)
+  {
+    try {
+      Schema schema = new Schema(null, args[0], true);
+      BtreeDictParameters tmapParams = new BtreeDictParameters(schema, "TMAP");
+      if (tmapParams.readState() == false)
+	{
+	  tmapParams.setBlockSize(2048);
+	  tmapParams.setRoot(0);
+	  tmapParams.setFreeID(1);
+	}
+      FullBtreeDict dict = new FullBtreeDict(tmapParams, true);
+      int freeID = tmapParams.getFreeID();
+    
+      LineNumberReader in = new LineNumberReader(new BufferedReader
+						 (new FileReader(args[1])));
+      String line;
+      while ((line = in.readLine()) != null)
+	{
+	  StringTokenizer tokens = new StringTokenizer(line, " ");
+	  while (tokens.hasMoreTokens())
+	    {
+	      String token = tokens.nextToken();
+	      if (token.equals("storing"))
+		dict.store(tokens.nextToken(), freeID++);
+	      else if (token.equals("fetching"))
+		  dict.fetch(tokens.nextToken());
+	    }
+	}
+      in.close();
+    }
+    catch (Exception e) {
+      e.printStackTrace();
+    }
+  }
+ 
+ /**
+   * Debug code
+   */
+
+  private boolean debug=false;
+  private void debug(String msg) {
+    if (debug) {
+      System.err.println("FullBtreeDict: "+msg);
+    }
+  }
+}
+
diff --git a/jhMaster/JSearch/indexer/com/sun/java/help/search/HTMLIndexerKit.java b/jhMaster/JSearch/indexer/com/sun/java/help/search/HTMLIndexerKit.java
new file mode 100644
index 0000000000000000000000000000000000000000..a7f05174c5e6ffd220be0d0f7cb56f4f34f7110e
--- /dev/null
+++ b/jhMaster/JSearch/indexer/com/sun/java/help/search/HTMLIndexerKit.java
@@ -0,0 +1,1211 @@
+/*
+ * @(#)HTMLIndexerKit.java	1.26 06/10/30
+ * 
+ * Copyright (c) 2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @(#) HTMLIndexerKit.java 1.26 - last change made 10/30/06
+ */
+
+package com.sun.java.help.search;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.io.*;
+import java.net.MalformedURLException;
+import java.net.URL;
+import javax.swing.text.*;
+import javax.swing.text.html.*;
+import java.util.*;
+import javax.help.search.IndexerKit;
+import javax.help.search.IndexBuilder;
+import javax.help.search.ConfigFile;
+
+/**
+ * This is the default implementation of html parsing.
+ * It can be subclasses to use a different parser and
+ * receiver.
+ *
+ * @author  Roger D. Brinkley
+ * @version %I	%G
+ */
+public class HTMLIndexerKit extends DefaultIndexerKit{
+   
+    /**
+     * Constructs an HTMLEditorKit
+     */
+    public HTMLIndexerKit() {
+
+    }
+
+    /**
+     * Create a copy of the editor kit.  This
+     * allows an implementation to serve as a prototype
+     * for others, so that they can be quickly created.
+     *
+     * @return the copy
+     */
+    public Object clone() {
+	return new HTMLIndexerKit();
+    }
+
+    /**
+     * Get the MIME type of the data that this
+     * kit represents support for.  This kit supports
+     * the type <code>text/html</code>.
+     *
+     * @return the type
+     */
+    public String getContentType() {
+	return "text/html";
+    }
+
+    /**
+     * Create and initialize a model from the given
+     * stream which is expected to be in a format appropriate
+     * for this kind of kit.  This is implemented to read
+     * html 3.2 text.
+     * 
+     * @param in  The stream to read from
+     * @param file The file name being parsed
+     * @param ignoreCharset Ignore the CharacterSet when parsing
+     * @param builder The IndexBuilder for the full text insertion.
+     * @param config The indexer configuration information
+     * @exception IOException on any I/O error
+     */
+    public void parse(Reader in, String file, boolean ignoreCharset,
+		      IndexBuilder builder,
+		      ConfigFile config) throws IOException{
+
+	this.builder = builder;
+	this.config = config;
+	this.file = file;
+	documentStarted = false;
+
+	HTMLEditorKit.Parser p = getParser();
+	if (p == null) {
+	    throw new IOException("Can't load parser");
+	}
+	if (defaultCallback == null) {
+	    defaultCallback = getParserCallback(this);
+	}
+	defaultCallback.initialize();
+	try {
+	    p.parse(in, defaultCallback, ignoreCharset);
+	} catch (javax.swing.text.ChangedCharSetException e4) {
+	    throw new com.sun.java.help.search.ChangedCharSetException
+		(e4.getCharSetSpec(), 
+		 e4.keyEqualsCharSet());
+	}
+		    
+	try {
+	    defaultCallback.flush();
+	} catch (BadLocationException e3) {
+	    throw new IOException("Can't flush parser");
+	}
+
+	try {
+	    storeTitle(defaultCallback.getTitle());
+	    endStoreDocument();
+	} catch (Exception e2) {
+	    throw new IOException("Can't store title");
+	}
+
+	this.builder = null;
+	this.config = null;
+    }
+
+    /**
+     * Fetch the parser to use for reading html streams.
+     * This can be reimplemented to provide a different
+     * parser.  The default implementation is loaded dynamically
+     * to avoid the overhead of loading the default parser if
+     * it's not used.  The default parser is the HotJava parser
+     * using an html 3.2 dtd.
+     */
+    protected HTMLEditorKit.Parser getParser() {
+	if (defaultParser == null) {
+	    try {
+                Class c = Class.forName("javax.swing.text.html.parser.ParserDelegator");
+                defaultParser = (HTMLEditorKit.Parser) c.newInstance();
+	    } catch (Throwable e) {
+		e.printStackTrace();
+	    }
+	}
+	return defaultParser;
+    }
+
+    /**
+     * Fetch the parser callback to use to parse the
+     * html.  This is implemented to return an instance of
+     * HTMLEditorKit.HTMLParserCallback.  Subclasses can reimplement this
+     * method to change how the document gets parsed
+     */
+    public HTMLParserCallback getParserCallback(IndexerKit kit) {
+	return new HTMLParserCallback(kit);
+    }
+    // --- variables ------------------------------------------
+
+    private static HTMLEditorKit.Parser defaultParser = null;
+    private static HTMLParserCallback defaultCallback = null;
+
+    private static char[] NEWLINE;
+
+    static {
+	NEWLINE = new char[1];
+	NEWLINE[0] = '\n';
+    }
+
+    /**
+     * An html reader to load an html document with an html
+     * element structure.  This is a set of callbacks from
+     * the parser, implemented to create a set index tokens
+     */ 
+    public class HTMLParserCallback extends HTMLEditorKit.ParserCallback {
+
+	private IndexerKit kit;
+	private String title;
+	private String header;
+	private boolean firstHeader;
+	private int currentPos;
+	private boolean receivedEndHTML;
+	private boolean insertAfterImplied;
+	private boolean inParagraph;
+	private boolean impliedP;
+	private boolean inPre;
+	private boolean inTextArea;
+	private boolean inTitle;
+	private boolean lastWasNewline;
+	private boolean emptyAnchor;
+	private boolean inBody;
+	private boolean foundInsertTag;
+	private boolean inHead;
+	private boolean inStyle;
+	private boolean inOption;
+	private boolean inFirstHeader;
+	private boolean startTagType;
+	private boolean preservesUnknownTags;
+	Hashtable tagMap;
+	int inBlock;	
+	Stack tagStack;
+	String defaultLang;
+	String lastLang;
+
+	// LangElement is a simple little internal class to keep
+	// track of tags and the langs
+	private class LangElement {
+
+	    HTML.Tag tag;
+	    String lang;
+
+	    public LangElement (HTML.Tag tag, String lang) {
+		this.tag = tag;
+		this.lang = lang;
+	    }
+
+	    public HTML.Tag getTag() {
+		return tag;
+	    }
+
+	    public String getLang() {
+		return lang; 
+	    }
+	}
+	    
+
+        public HTMLParserCallback(IndexerKit kit) {
+	    this.kit = kit;
+	    tagMap = new Hashtable(57);
+	    TagAction na = new TagAction();
+	    TagAction ba = new BlockAction();
+	    TagAction pa = new ParagraphAction();
+	    TagAction ca = new CharacterAction();
+	    TagAction sa = new SpecialAction();
+	    TagAction fa = new FormAction();
+	    TagAction ha = new HiddenAction();
+	    TagAction conv = new ConvertAction();
+
+	    // register handlers for the well known tags
+	    tagMap.put(HTML.Tag.A, new AnchorAction());
+	    tagMap.put(HTML.Tag.ADDRESS, ca);
+	    tagMap.put(HTML.Tag.APPLET, ha);
+	    tagMap.put(HTML.Tag.AREA, new AreaAction());
+	    tagMap.put(HTML.Tag.B, ca);
+	    tagMap.put(HTML.Tag.BASE, new BaseAction());
+	    tagMap.put(HTML.Tag.BASEFONT, ca);
+	    tagMap.put(HTML.Tag.BIG, ca);
+	    tagMap.put(HTML.Tag.BLOCKQUOTE, ba);
+	    tagMap.put(HTML.Tag.BODY, ba);
+	    tagMap.put(HTML.Tag.BR, sa);
+	    tagMap.put(HTML.Tag.CAPTION, ba);
+	    tagMap.put(HTML.Tag.CENTER, ba);
+	    tagMap.put(HTML.Tag.CITE, ca);
+	    tagMap.put(HTML.Tag.CODE, ca);
+	    tagMap.put(HTML.Tag.DD, ba);
+	    tagMap.put(HTML.Tag.DFN, ca);
+	    tagMap.put(HTML.Tag.DIR, ba);
+	    tagMap.put(HTML.Tag.DIV, ba);
+	    tagMap.put(HTML.Tag.DL, ba);
+	    tagMap.put(HTML.Tag.DT, pa);
+	    tagMap.put(HTML.Tag.EM, ca);
+	    tagMap.put(HTML.Tag.FONT, conv);
+	    tagMap.put(HTML.Tag.FORM, new FormTagAction());
+	    tagMap.put(HTML.Tag.FRAME, sa);
+	    tagMap.put(HTML.Tag.FRAMESET, ba);
+	    tagMap.put(HTML.Tag.H1, pa);
+	    tagMap.put(HTML.Tag.H2, pa);
+	    tagMap.put(HTML.Tag.H3, pa);
+	    tagMap.put(HTML.Tag.H4, pa);
+	    tagMap.put(HTML.Tag.H5, pa);
+	    tagMap.put(HTML.Tag.H6, pa);
+	    tagMap.put(HTML.Tag.HEAD, new HeadAction());
+	    tagMap.put(HTML.Tag.HR, sa);
+	    tagMap.put(HTML.Tag.HTML, ba);
+	    tagMap.put(HTML.Tag.I, conv);
+	    tagMap.put(HTML.Tag.IMG, sa);
+	    tagMap.put(HTML.Tag.INPUT, fa);
+	    tagMap.put(HTML.Tag.ISINDEX, new IsindexAction());
+	    tagMap.put(HTML.Tag.KBD, ca);
+	    tagMap.put(HTML.Tag.LI, ba);
+	    tagMap.put(HTML.Tag.LINK, new LinkAction());
+	    tagMap.put(HTML.Tag.MAP, new MapAction());
+	    tagMap.put(HTML.Tag.MENU, ba);
+	    tagMap.put(HTML.Tag.META, new MetaAction());
+	    // NOBR isn't publicly available so workaround it.
+	    HTML.Tag tag = HTML.getTag("NOBR");
+	    if (tag != null) {
+		tagMap.put(tag, ca);
+	    }
+	    tagMap.put(HTML.Tag.NOFRAMES, ba);
+	    tagMap.put(HTML.Tag.OBJECT, sa);
+	    tagMap.put(HTML.Tag.OL, ba);
+	    tagMap.put(HTML.Tag.OPTION, fa);
+	    tagMap.put(HTML.Tag.P, pa);
+	    tagMap.put(HTML.Tag.PARAM, new ObjectAction());
+	    tagMap.put(HTML.Tag.PRE, new PreAction());
+	    tagMap.put(HTML.Tag.SAMP, ca);
+	    tagMap.put(HTML.Tag.SCRIPT, ha);
+	    tagMap.put(HTML.Tag.SELECT, fa);
+	    tagMap.put(HTML.Tag.SMALL, ca);
+	    tagMap.put(HTML.Tag.STRIKE, conv);
+	    tagMap.put(HTML.Tag.S, ca);
+	    tagMap.put(HTML.Tag.STRONG, ca);
+	    tagMap.put(HTML.Tag.STYLE, new StyleAction());
+	    tagMap.put(HTML.Tag.SUB, conv);
+	    tagMap.put(HTML.Tag.SUP, conv);
+	    tagMap.put(HTML.Tag.TABLE, ba);
+	    tagMap.put(HTML.Tag.TD, ba);
+	    tagMap.put(HTML.Tag.TEXTAREA, fa);
+	    tagMap.put(HTML.Tag.TH, ba);
+	    tagMap.put(HTML.Tag.TITLE, new TitleAction());
+	    tagMap.put(HTML.Tag.TR, ba);
+	    tagMap.put(HTML.Tag.TT, ca);
+	    tagMap.put(HTML.Tag.U, conv);
+	    tagMap.put(HTML.Tag.UL, ba);
+	    tagMap.put(HTML.Tag.VAR, ca);
+	}
+
+	public void initialize() {
+	    title = null;
+	    header = null;
+	    firstHeader = true;
+	    currentPos = 0;
+	    receivedEndHTML = false;
+	    insertAfterImplied = false;
+	    inParagraph = false;
+	    impliedP = false;
+	    inPre = false;
+	    inTitle = false;
+	    inOption = false;
+	    inFirstHeader = false;
+	    startTagType = false;
+	    emptyAnchor = false;
+	    inBlock = 0;
+	    tagStack = new Stack();
+	    defaultLang = kit.getLocale().toString();
+	    lastLang = defaultLang;
+	    inTextArea = false;
+	    lastWasNewline = false;
+	    inBody = false;
+	    foundInsertTag = true;
+	    preservesUnknownTags = true;
+	    inHead = false;
+	    inStyle = false;
+	}
+
+	public String getTitle() {
+	    if (title == null || title.length() < 1) {
+		title = header;
+		if (title == null || title.length() < 1) {
+		    title = "No Title";
+		}
+	    }
+	    return title;
+	}
+
+	// -- ParserCallback methods --------------------
+
+	/**
+	 * This is the last method called on the reader.  It allows
+	 * any pending changes to be flushed into the document.  
+	 * Since this is currently loading synchronously, the entire
+	 * set of changes are pushed in at this point.
+	 */
+        public void flush() throws BadLocationException {
+	    // Nothing needs to be done here
+	}
+
+	/**
+	 * Called by the parser to indicate a block of text was
+	 * encountered.
+	 */
+        public void handleText(char[] data, int pos) {
+	    if (receivedEndHTML) {
+		return;
+	    }
+	    if (inTextArea) {
+		// don't do anything
+	    } else if (inPre) {
+		preContent(data);
+	    } else if (inTitle) {
+		titleContent(new String(data));
+	    } else if (inOption) {
+		// Nothing to do here
+	    } else if (inStyle) {
+		// don't do anything
+	    } else if (inBlock > 0) {
+		// Added test for first header to set the 
+		// header content
+		if (inFirstHeader) {
+		    headerContent(new String(data));
+		}
+		if (!foundInsertTag && insertAfterImplied) {
+		    // Assume content should be added.
+		    foundInsertTag(false);
+		    foundInsertTag = true;
+		    inParagraph = impliedP = true;
+		}
+		if (data.length >= 1) {
+		    addContent(data, 0, data.length);
+		}
+	    }
+	}
+
+	/**
+	 * Callback from the parser.  Route to the appropriate
+	 * handler for the tag. 
+	 * This method differes from HTMLDcoument since there
+	 * is not the possibility of doing a mid insert in the
+	 * document and we don't really need to be concerned with
+	 * the construction of the style sheet.
+	 */
+	public void handleStartTag(HTML.Tag t, MutableAttributeSet a, int pos) {
+            if (receivedEndHTML) {
+                return;
+            }
+	    if (!inBody && t == HTML.Tag.BODY) {
+		inBody = true;
+	    }
+	    TagAction action = (TagAction) tagMap.get(t);
+	    if (action != null) {
+		action.start(t, a);
+	    }
+	}
+
+        public void handleComment(char[] data, int pos) {
+            if (receivedEndHTML) {
+		// don't do anything here
+                return;
+            }
+	    if (inStyle) {
+		// don't do anything here
+	    } else if (preservesUnknownTags) {
+		if (inBlock == 0) {
+                    // Comment outside of body, will not be able to show it,
+                    // but can add it as a property on the Document.
+		    // In the indexer we don't care though so
+		    // do nothing.
+		    return;
+		}
+		SimpleAttributeSet sas = new SimpleAttributeSet();
+		sas.addAttribute(HTML.Attribute.COMMENT, new String(data));
+		addSpecialElement(HTML.Tag.COMMENT, sas);
+		debug ("comment added currentPos=" + currentPos);
+	    }
+	}
+
+	/**
+	 * Callback from the parser.  Route to the appropriate
+	 * handler for the tag.
+	 * 
+	 * Ignore the midInsert statements in HTMLDocument
+	 */
+	public void handleEndTag(HTML.Tag t, int pos) {
+	    if (receivedEndHTML) {
+		return;
+	    }
+            if (t == HTML.Tag.HTML) {
+                receivedEndHTML = true;
+            }
+	    if (t == HTML.Tag.BODY) {
+		inBody = false;
+	    }
+	    TagAction action = (TagAction) tagMap.get(t);
+	    if (action != null) {
+		action.end(t);
+	    }
+	}
+
+	/**
+	 * Callback from the parser.  Route to the appropriate
+	 * handler for the tag.
+	 *
+	 * Ignore the midInsert and style statements in HTMLDocument
+	 */
+	public void handleSimpleTag(HTML.Tag t, MutableAttributeSet a, int pos) {
+	    if (receivedEndHTML) {
+		return;
+	    }
+
+	    TagAction action = (TagAction) tagMap.get(t);
+	    if (action != null) {
+		action.start(t, a);
+		action.end(t);
+	    } else if (preservesUnknownTags) {
+		addSpecialElement(t, a);
+	    }
+	}
+
+	// ---- tag handling support ------------------------------
+
+	/**
+	 * Register a handler for the given tag.  By default
+	 * all of the well-known tags will have been registered.
+	 * This can be used to change the handling of a particular
+	 * tag or to add support for custom tags.
+	 */
+        protected void registerTag(HTML.Tag t, TagAction a) {
+	    tagMap.put(t, a);
+	}
+
+	/**
+	 * This is an action to be performed in response
+	 * to parsing a tag.  This allows customization
+	 * of how each tag is handled and avoids a large
+	 * switch statement.
+	 */
+	public class TagAction {
+
+	    /**
+	     * Called when a start tag is seen for the
+	     * type of tag this action was registered
+	     * to.  The tag argument indicates the actual
+	     * tag for those actions that are shared across
+	     * many tags. 
+	     * 
+	     * Different from HTMLDocument it doesn't ignore
+	     * the tag.
+	     */
+	    public void start(HTML.Tag t, MutableAttributeSet a) {
+		String lang = (String) a.getAttribute(HTML.Attribute.LANG);
+		if (lang == null) {
+		    lang = lastLang;
+		}
+		addTag(t, lang);
+	    }
+
+	    /**
+	     * Called when an end tag is seen for the
+	     * type of tag this action was registered
+	     * to.  The tag argument indicates the actual
+	     * tag for those actions that are shared across
+	     * many tags. 
+	     * 
+	     * Different from HTMLDocument it doesn't ignore
+	     * the tag.
+	     */
+	    public void end(HTML.Tag t) {
+		removeTag(t);
+	    }
+
+	}
+
+	public class BlockAction extends TagAction {
+
+	    public void start(HTML.Tag t, MutableAttributeSet attr) {
+		blockOpen(t, attr);
+		String lang = (String) attr.getAttribute(HTML.Attribute.LANG);
+		if (lang == null) {
+		    lang = lastLang;
+		}
+		addTag(t, lang);
+	    }
+
+	    public void end(HTML.Tag t) {
+		blockClose(t);
+		removeTag(t);
+	    }
+	}
+
+        /**
+         * Action used for the actual element form tag. This is named such
+         * as there was already a public class named FormAction. 
+	 * 
+	 * Unlike HTMLDocument there is no need to setup/destroy
+	 * a ButtonGroup
+         */
+        private class FormTagAction extends BlockAction {
+            public void start(HTML.Tag t, MutableAttributeSet attr) {
+                super.start(t, attr);
+		// do nothing else
+            }
+
+	    public void end(HTML.Tag t) {
+                super.end(t);
+		// do nothing else
+            }
+        }
+
+
+	public class ParagraphAction extends BlockAction {
+
+	    public void start(HTML.Tag t, MutableAttributeSet a) {
+		// trap the first header as a substitute title if needed
+		if (firstHeader && 
+		    ((t == HTML.Tag.H1) || (t == HTML.Tag.H2) ||
+		     (t == HTML.Tag.H3) || (t == HTML.Tag.H4) ||
+		     (t == HTML.Tag.H5) || (t == HTML.Tag.H6))) {
+		    inFirstHeader = true;
+		}
+		// addTag done in super
+		super.start(t, a);
+		inParagraph = true;
+	    }
+
+	    public void end(HTML.Tag t) {
+		// trapped the first header as a substitute title if needed
+		if (firstHeader && 
+		    ((t == HTML.Tag.H1) || (t == HTML.Tag.H2) ||
+		     (t == HTML.Tag.H3) || (t == HTML.Tag.H4) ||
+		     (t == HTML.Tag.H5) || (t == HTML.Tag.H6))) {
+		    inFirstHeader = false;
+		    firstHeader = false;
+		}
+		// removeTag done in super
+		super.end(t);
+		inParagraph = false;
+	    }
+	}
+
+	public class SpecialAction extends TagAction {
+
+	    public void start(HTML.Tag t, MutableAttributeSet a) {
+		String lang = (String) a.getAttribute(HTML.Attribute.LANG);
+		if (lang == null) {
+		    lang = lastLang;
+		}
+		addTag(t, lang);
+		addSpecialElement(t, a);
+	    }
+	    // removeTag is handled in super class
+	}
+
+	public class IsindexAction extends TagAction {
+
+	    public void start(HTML.Tag t, MutableAttributeSet a) {
+		blockOpen(HTML.Tag.IMPLIED, new SimpleAttributeSet());
+		addSpecialElement(t, a);
+		blockClose(HTML.Tag.IMPLIED);
+	    }
+
+	}
+
+	public class HiddenAction extends TagAction {
+
+	    public void start(HTML.Tag t, MutableAttributeSet a) {
+		String lang = (String) a.getAttribute(HTML.Attribute.LANG);
+		if (lang == null) {
+		    lang = lastLang;
+		}
+		addTag(t, lang);
+		addSpecialElement(t, a);
+	    }
+
+	    public void end(HTML.Tag t) {
+		if (!isEmpty(t)) {
+		    MutableAttributeSet a = new SimpleAttributeSet();
+		    a.addAttribute(HTML.Attribute.ENDTAG, "true");
+		    addSpecialElement(t, a);
+		} 
+		removeTag(t);
+	    }
+
+	    private boolean isEmpty(HTML.Tag t) {
+		if (t == HTML.Tag.APPLET ||
+		    t == HTML.Tag.TITLE ||
+		    t == HTML.Tag.SCRIPT) {
+		    return false;
+		}
+		return true;
+	    }
+	}
+
+	/**
+	 * Subclass of HiddenAction to set the content type for style sheets,
+	 * and to set the name of the default style sheet.
+	 * 
+	 * None of this method is really needed for the Indexer.
+	 * Don't do anything related tot he style sheet and just
+	 * take the actions of HiddenAction to record the position
+	 */
+	class MetaAction extends HiddenAction {
+
+	    public void start(HTML.Tag t, MutableAttributeSet a) {
+		// ignore all the style sheet setting code
+		super.start(t, a);
+	    }
+
+	    private boolean isEmpty(HTML.Tag t) {
+		return true;
+	    }
+	}
+
+
+	/**
+	 * End if overridden to create the necessary stylesheets that
+	 * are referenced via the link tag. It is done in this manner
+	 * as the meta tag can be used to specify an alternate style sheet,
+	 * and is not guaranteed to come before the link tags.
+	 *
+	 * For the indexer we don't care much about the style
+	 * sheets.
+	 */
+	class HeadAction extends BlockAction {
+
+	    public void start(HTML.Tag t, MutableAttributeSet a) {
+		inHead = true;
+		super.start(t, a);
+	    }
+
+	    public void end(HTML.Tag t) {
+		inHead = inStyle = false;
+		// ignore the StyleSheet statements
+		super.end(t);
+	    }
+	}
+
+	/**
+	 * A subclass to add the AttributeSet to styles if the
+	 * attributes contains an attribute for 'rel' with value
+	 * 'stylesheet' or 'alternate stylesheet'.
+	 *
+	 * For the indexer we don't care about style sheets.
+	 */
+	class LinkAction extends HiddenAction {
+
+	    public void start(HTML.Tag t, MutableAttributeSet a) {
+		// ignore the style sheet statements
+		super.start(t, a);
+	    }
+	}
+
+	/**
+	 * Don't do anything for Maps in Indexer. It just stores
+	 * the information in a property HashTable.
+	 */
+	class MapAction extends TagAction {
+	}
+
+
+	/**
+	 * Don't do anthing for an Area action for Indexer. 
+	 * It's stored locally in HTMLDocument and doesn't
+	 * require an entry as a tag
+	 */
+	class AreaAction extends TagAction {
+	}
+
+
+	/**
+	 * Handle style actions
+	 * 
+	 * Ignore the storing the styles as HTMLDocument does
+	 */
+	class StyleAction extends TagAction {
+
+	    public void start(HTML.Tag t, MutableAttributeSet a) {
+		if (inHead) {
+		    inStyle = true;
+		}
+		super.start(t, a);
+	    }
+
+	    public void end(HTML.Tag t) {
+		inStyle = false;
+		super.end(t);
+	    }
+	}
+	    
+
+	public class PreAction extends BlockAction {
+
+	    public void start(HTML.Tag t, MutableAttributeSet attr) {
+		inPre = true;
+		blockOpen(t, attr);
+		attr.addAttribute(CSS.Attribute.WHITE_SPACE, "pre");
+		blockOpen(HTML.Tag.IMPLIED, attr);
+		String lang = (String) attr.getAttribute(HTML.Attribute.LANG);
+		if (lang == null) {
+		    lang = lastLang;
+		}
+		addTag(t, lang);
+	    }
+
+	    public void end(HTML.Tag t) {
+		blockClose(HTML.Tag.IMPLIED);
+		// set inPre to false after closing, so that if a newline
+		// is added it won't generate a blockOpen.
+		inPre = false;
+		blockClose(t);
+		removeTag(t);
+	    }
+	}
+
+	public class CharacterAction extends TagAction {
+
+	    /**
+	     * In the indexer we don't care about character style
+	     * and the foundInsertTag will always be true so there 
+	     * really isn't much to do here
+	     *
+	     */
+	    public void start(HTML.Tag t, MutableAttributeSet a) {
+		String lang = (String) a.getAttribute(HTML.Attribute.LANG);
+		if (lang == null) {
+		    lang = lastLang;
+		}
+		addTag(t, lang);
+	    }
+
+	    public void end(HTML.Tag t) {
+		removeTag(t);
+	    }
+	}
+
+	/**
+	 * Provides conversion of HTML tag/attribute
+	 * mappings that have a corresponding StyleConstants
+	 * and CSS mapping.  The conversion is to CSS attributes.
+	 *
+	 * For the indexer we really don't care much. We'll keep
+	 * the method here for consistency sake, but it really 
+	 * isn't needed.
+	 */
+	class ConvertAction extends TagAction {
+	}
+
+	class AnchorAction extends CharacterAction {
+            // This class has a dependancy on the "one[0]" character
+	    // used in javax.swing.text.html.HTMLDocument$AnchorAction
+	    // we need to ensure we use the same character value.
+	    private boolean post4207472 = isPost4207472();
+
+	    public void start(HTML.Tag t, MutableAttributeSet attr) {
+		// set flag to catch empty anchors
+		emptyAnchor = true;
+		// addTag done in super
+		super.start(t, attr);
+	    }
+	
+	    public void end(HTML.Tag t) {
+		if (emptyAnchor) {
+		    // if the anchor was empty it was probably a
+		    // named anchor point and we don't want to throw
+		    // it away.
+		    char[] one = new char[1];
+		    if (post4207472)
+			one[0] = '\n';
+		    else
+		        one[0] = ' ';
+		    debug ("emptyAnchor currentPos=" + currentPos);
+		    addContent(one, 0, 1);
+                }
+		// remove tag done in super
+		super.end(t);
+	    }
+	   private boolean isPost4207472()  {
+		try {
+	   	    String ver = System.getProperty("java.version"); 
+		    int major = Integer.parseInt(ver.substring(2,3));
+		    int minor = 0;
+		    // allow for FCS case - we leave minor as 0 if dealing with FCS
+		    if (ver.length() > 6)
+		    	minor = Integer.parseInt(ver.substring(6,8)); 
+		    if ((major > 5 ) || (major==5 && minor >= 4)) {
+		    	return true;
+		    } else {
+		    	return false;
+		    }
+		} catch (Exception e) {
+		    debug ("Exception in isPost4207472 : " + e);
+		    return true;  // assume true if we encounter problem
+	        }	
+	   }
+	}
+
+	class TitleAction extends HiddenAction {
+
+	    public void start(HTML.Tag t, MutableAttributeSet attr) {
+		inTitle = true;
+		super.start(t, attr);
+	    }
+	
+	    public void end(HTML.Tag t) {
+		inTitle = false;
+		super.end(t);
+	    }
+	}
+
+	class BaseAction extends TagAction {
+
+	    // Nothing here for indexer
+	}
+
+
+	class ObjectAction extends SpecialAction {
+
+	    public void start(HTML.Tag t, MutableAttributeSet a) {
+		if (t == HTML.Tag.PARAM) {
+		    // don't do anything if a parameter
+		} else {
+		    super.start(t, a);
+		}
+	    }
+
+	    public void end(HTML.Tag t) {
+		if (t != HTML.Tag.PARAM) {
+		    super.end(t);
+		}
+	    }
+
+	}
+
+	public class FormAction extends SpecialAction {
+
+	    /**
+	     * Ignore INPUT and Select. Only be concerned with
+	     * TEXTAREA and OPTION
+	     */
+	    public void start(HTML.Tag t, MutableAttributeSet attr) {
+		if (t == HTML.Tag.TEXTAREA) {
+		    inTextArea = true;
+		}
+
+		// Occupy one space for the element, unless this is an option.
+		if (t == HTML.Tag.OPTION) {
+		    //options don't take any room. They are internal to selects
+		} else {
+		    super.start(t, attr);
+		}
+	    }
+
+	    public void end(HTML.Tag t) {
+		if (t == HTML.Tag.TEXTAREA) {
+		    inTextArea = false;
+		}
+
+		if (t == HTML.Tag.OPTION) {
+		    // ignore options
+		} else {
+		    super.end(t);
+		} 
+	    }
+
+	}
+
+	// --- utility methods used by the reader ------------------
+
+	/**
+	 * Set the title for the doc
+	 */
+	protected void titleContent(String s) {
+	    if (title == null) {
+		title = new String(s);
+	    } else {
+		title.concat(s);
+	    }
+	}
+	
+	/**
+	 * Set the first header for the doc
+	 */
+	protected void headerContent(String s) {
+	    if (header == null) {
+		header = new String(s);
+	    } else {
+		header.concat(s);
+	    }
+	}
+
+	/**
+	 * Add the given content that was encountered in a 
+	 * PRE element.  This synthesizes lines to hold the
+	 * runs of text, and makes calls to addContent to
+	 * actually add the text.
+	 */
+	protected void preContent(char[] data) {
+	    int last = 0;
+	    for (int i = 0; i < data.length; i++) {
+		if (data[i] == '\n') {
+		    debug ("preContent currentPos=" + currentPos);
+		    addContent(data, last, i - last + 1);
+		    blockClose(HTML.Tag.IMPLIED);
+		    MutableAttributeSet a = new SimpleAttributeSet();
+		    a.addAttribute(CSS.Attribute.WHITE_SPACE, "pre");
+		    blockOpen(HTML.Tag.IMPLIED, a);
+		    last = i + 1;
+		}
+	    }
+	    if (last < data.length) {
+		debug ("preContent currentPos=" + currentPos);
+		addContent(data, last, data.length - last);
+	    }
+	}
+
+	/**
+	 * Add an instruction to the parse buffer to create a 
+	 * block element with the given attributes.
+	 */
+	protected void blockOpen(HTML.Tag t, MutableAttributeSet attr) {
+	    debug ("blockOpen");
+	    if (impliedP) {
+		blockClose(HTML.Tag.IMPLIED);
+	    }
+		
+	    inBlock++;
+	    if (!canInsertTag(t, attr, true)) {
+		return;
+	    }
+	    startTagType = true;
+	    lastWasNewline = false;
+	    // parse buffer code not used in indexer
+	}
+
+	/**
+	 * Add an instruction to the parse buffer to close out
+	 * a block element of the given type.
+	 */
+	protected void blockClose(HTML.Tag t) {
+	    debug ("blockClose");
+	    inBlock --;
+
+	    if (!foundInsertTag) {
+		return;
+	    }
+
+	    // Add a new line, if the last character wasn't one. This is
+	    // needed for proper positioning of the cursor.
+	    if(!lastWasNewline) {
+		debug ("blockClose adding NEWLINE currentPos=" + currentPos);
+		addContent(NEWLINE, 0, 1, false);
+		lastWasNewline = true;
+	    }
+
+	    if (impliedP) {
+		impliedP = false;
+		inParagraph = false;
+                if (t != HTML.Tag.IMPLIED) {
+                    blockClose(HTML.Tag.IMPLIED);
+                }
+	    }
+	    
+	    // This is different from HTMLReader. I don't keep parseBuffer
+	    // so I'll use the boolean startTagType instead.
+	    //
+	    // an open/close with no content will be removed, so we
+	    // add a space of content to keep the element being formed.
+	    if (startTagType) {
+		char[] one = new char[1];
+		one[0] = ' ';
+		debug ("blockclose open/close nocontent currentPos=" + currentPos);
+		addContent(one, 0, 1);
+	    }
+	    startTagType = false;
+	}
+
+	/**
+	 * Add some text with the current character attributes.
+	 *
+	 * @param embedded the attributes of an embedded object.
+	 */
+	protected void addContent(char[] data, int offs, int length) {
+	    addContent(data, offs, length, true);
+	}
+
+	/**
+	 * Add some text with the current character attributes.
+	 *
+	 * @param embedded the attributes of an embedded object.
+	 */
+	protected void addContent(char[] data, int offs, int length,
+				  boolean generateImpliedPIfNecessary) {
+	    debug ("addContent");
+	    if (!foundInsertTag) {
+		return;
+	    }
+
+	    if (generateImpliedPIfNecessary && (! inParagraph) && (! inPre)) {
+		blockOpen(HTML.Tag.IMPLIED, new SimpleAttributeSet());
+		inParagraph = true;
+		impliedP = true;
+	    }
+	    emptyAnchor = false;
+
+	    // This is different from HTMLDocument. The indexer doesn't use
+	    // parseBuffer. Instead pass the strings over to IndexerKit to
+	    // parse the string into tokens. Also set startTagType to false
+	    // to simulate that portion of parseBuffer
+	    debug ("Pre parseIntoTokens String=" + new String(data, offs, length) + " currentPos=" + currentPos);
+	    startTagType = false;
+	    currentPos = kit.parseIntoTokens(new String(data, offs, length), 
+					     currentPos);
+	    debug ("Post parseIntoTokens currentPos=" + currentPos);
+
+	    // No flushing like HTMLDocument but set the lastWasNewline
+	    // appropriately
+	    if(length > 0) {
+		lastWasNewline = (data[offs + length - 1] == '\n');
+	    }
+	}
+
+	/**
+	 * Add content that is basically specified entirely
+	 * in the attribute set.
+	 */
+	protected void addSpecialElement(HTML.Tag t, MutableAttributeSet a) {
+	    if ((t != HTML.Tag.FRAME) && (! inParagraph) && (! inPre)) {
+		blockOpen(HTML.Tag.IMPLIED, new SimpleAttributeSet());
+		inParagraph = true;
+		impliedP = true;
+	    }
+
+	    if (!canInsertTag(t, a, true)) {
+		return;
+	    }
+	    emptyAnchor = false;
+
+	    // This is different from HTMLDocument. The indexer doesn't use
+	    // parseBuffer. Just increment to currentPos to simulate the
+	    // addition
+	    currentPos += 1;
+	    debug ("addingSpecialElement tag=" + t + " currentPos=" + currentPos);
+	    startTagType = false;
+
+	    // Set this to avoid generating a newline for frames, frames
+	    // shouldn't have any content, and shouldn't need a newline.
+	    if (t == HTML.Tag.FRAME) {
+		lastWasNewline = true;
+	    }
+	}
+
+	/**
+	 * Returns true if can insert starting at <code>t</code>. This 
+	 * will return false if the insert tag is set, and hasn't been found
+	 * yet.
+	 */
+	private boolean canInsertTag(HTML.Tag t, AttributeSet attr,
+				     boolean isBlockTag) {
+	    if (!foundInsertTag) {
+		foundInsertTag(isBlockTag);
+		return false;
+	    }
+	    return true;
+	}
+
+	private boolean isInsertTag(HTML.Tag tag) {
+	    return (false);
+	}
+
+	private void foundInsertTag(boolean isBlockTag) {
+	    foundInsertTag = true;
+	    // The rest of the code is differnt from HTMLDocument since we
+	    // don't need to worry about added to a document we don't care 
+	    // about adding a newline or pushing or poping
+	}
+
+	/**
+	 * addTag keeps track of tags and their lang attributes
+	 */
+	protected void addTag(HTML.Tag tag, String lang) {
+	    LangElement el = new LangElement(tag, lang);
+	    tagStack.push(el);
+	    if (lastLang.compareTo(lang) != 0) {
+		kit.setLocale(lang);
+		lastLang = lang;
+	    }
+	}
+
+	/**
+	 * removeTag removes a tag from the tagStack. The tagStack is
+	 * used to keep track of tags and locales
+	 */
+	protected void removeTag(HTML.Tag tag) {
+	    LangElement el;
+	    String name = tag.toString();
+	    String newLang=defaultLang;
+
+	    for (;;) {
+		if (tagStack.empty()) 
+		    break;
+		el = (LangElement) tagStack.pop();
+		if (el.getTag().toString().compareTo(name) == 0) {
+		    if (tagStack.empty()) {
+			newLang = defaultLang;
+		    } else {
+			el = (LangElement) tagStack.peek();
+			newLang = el.getLang();
+		    }
+		    break;
+		}
+	    }
+	    if (lastLang.compareTo(newLang) != 0) {
+		kit.setLocale(newLang);
+		lastLang = newLang;
+	    }
+	}
+	
+    }
+
+    /**
+     * Debug code
+     */
+
+    private boolean debugFlag=false;
+    private void debug(String msg) {
+        if (debugFlag) {
+            System.err.println("HTMLIndexerKit: "+msg);
+        }
+    }
+}
diff --git a/jhMaster/JSearch/indexer/com/sun/java/help/search/Indexer.java b/jhMaster/JSearch/indexer/com/sun/java/help/search/Indexer.java
new file mode 100644
index 0000000000000000000000000000000000000000..1bf29848435e12e70e7a3cd83101a2dd05b2e967
--- /dev/null
+++ b/jhMaster/JSearch/indexer/com/sun/java/help/search/Indexer.java
@@ -0,0 +1,546 @@
+/*
+ * @(#)Indexer.java	1.46 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @(#) Indexer.java 1.46 - last change made 10/30/06
+ */
+
+package com.sun.java.help.search;
+
+import java.io.*;
+import java.text.*;
+import java.net.*;
+import java.util.Vector;
+import java.util.Hashtable;
+import java.util.Locale;
+import javax.help.search.IndexerKit;
+import javax.help.search.ConfigFile;
+import com.sun.java.help.impl.HeaderParser;
+
+/**
+ * This class provides ...
+ *
+ *
+ * @version	1.46	10/30/06
+ * @author	Roger D. Brinkley
+ */
+
+public class Indexer {
+
+    /** The database directory name. */
+    String dbName = "JavaHelpSearch";
+
+    /** The stream for printing syntax errors */
+    PrintStream verbose=null;
+    PrintStream logStream=null;
+
+    /** The number of documents correctly parsed and compiled. */
+    short docNumber;
+
+    private DefaultIndexBuilder indexBuilder = null;
+
+    private ConfigFile config;
+    private String title;
+    private String header;
+    private boolean firstHeader=false;
+    String lastPCdata;
+    int currentPos;
+    boolean openTagSeen = false;
+    boolean inPre = false;
+    boolean inTitle = false;
+    boolean inFirstHeader = false;
+    boolean inOption = false;
+    int inBlock = 0;
+    String sourcepath;
+    /**
+     * Starts the application.
+     * @param args[]   the command line arguments
+     **/
+
+    public static void main(String args[]) {
+	Indexer compiler = new Indexer();
+	try {
+	    compiler.compile(args);
+	}
+	catch (Exception e) {
+	    e.printStackTrace();
+	}
+    }
+
+    /**
+     * Creates an initialised compiler.
+     **/
+
+    public Indexer() {
+	// Make sure the last character is a file separator
+	if (dbName.lastIndexOf("/")
+	    != dbName.length() - 1) {
+	    dbName = dbName.concat("/");
+	}
+	docNumber = 0;
+    }
+
+    /**
+     * Parses the <tt>.html</tt> files, and compiles the search database.
+     * @param args[]   the command line arguments
+     **/
+
+    public void compile(String args[]) throws Exception {
+	long parseTime, compileTime, startTime = System.currentTimeMillis();
+	int words;
+	String configFile = null;
+	Vector tmpfiles = new Vector();
+	Vector files = new Vector();
+	String file;
+	int size;
+	sourcepath="";
+	boolean nostopwords = false;
+	
+	for (int i=0; i < args.length ; i++) { 
+	    if(args[i].equals("-db")) {
+		if ((i + 1) < args.length) {
+		    dbName = args[++i];
+		    // Make sure the last character is a file separator
+		    if (dbName.lastIndexOf("/")
+			!= dbName.length() - 1) {
+			dbName = dbName.concat("/");
+		    }
+		} else {
+		    System.out.println (args[i] + "-db requires argument");
+		}
+	    }
+	    else if(args[i].equals("-sourcepath")) {
+		if ((i + 1) < args.length) {
+		    sourcepath = args[++i];
+		} else {
+		    System.out.println (args[i] + "-sourcepath requires argument");
+		}
+	    }	   
+	    else if(args[i].equals("-locale")) {
+		if ((i + 1) < args.length) {
+		    defaultLang= args[++i];
+		} else {
+		    System.out.println (args[i] + "-locale requires argument");
+		}
+	    }	   
+	    else if(args[i].equals("-logfile")) {
+		if ((i + 1) < args.length) {
+		    String logFile= args[++i];
+		    try {
+			logStream = new PrintStream(new FileOutputStream(logFile)
+						   ,true);
+			System.setErr(logStream);
+			System.setOut(logStream);
+			verbose = logStream;
+		    } catch (java.io.FileNotFoundException ex) {
+			System.out.println("Couldn't create logFile " + logFile);
+		    }
+		} else {
+		    System.out.println (args[i] + "-logfile requires argument");
+		}
+	    }	   
+	    else if(args[i].equals("-verbose")) verbose = System.out;
+	    else if(args[i].equals("-nostopwords")) nostopwords = true;
+	    else if(args[i].equals("-c")) {
+		if ((i + 1) < args.length) {
+		    configFile = args[++i];
+		} else {
+		    System.out.println (args[i] + "-c requires argument");
+		}
+	    }
+	    else if(args[i].startsWith("-")) {
+		System.out.println("Unknown argument '" + args[i] + "'");
+		showUsage();
+		return;
+	    } else {
+	        tmpfiles.addElement(args[i]);
+	    }
+	}
+
+	// read the config file
+	config = new ConfigFile (configFile, files, nostopwords);
+	// get the files from the config file
+	files = config.getFiles();
+
+	// adjust the passed with config parameters
+	size = tmpfiles.size();
+	for (int i=0; i < size; i++) {
+	    files = loadFiles ((String)tmpfiles.elementAt(i), files);
+	}
+
+	size = files.size();
+	if (size == 0) {
+		System.out.println("No files specified to index");
+		showUsage();
+		return;
+	}
+
+	indexBuilder= new DefaultIndexBuilder(dbName);
+	// set the stopwords in the indexBuilder
+	indexBuilder.storeStopWords(config.getStopWords());
+    
+	for (int i=0; i < size; i++) {
+	    file = (String) files.elementAt(i);
+	    URL url = new URL("file", "", sourcepath+file);
+	    InputStream in = url.openStream();
+	    URLConnection conn = url.openConnection();
+	    String type = conn.getContentType();
+	    setContentType(type);
+	    if (kit != null) {
+		try {
+		    if (verbose != null) {
+			verbose.println("   File: '" + file + "'");
+			verbose.println("    URL: '" + config.getURLString(file) + "'");
+		    }
+		    parseFile(in, file, false);
+		    in.close();
+		} catch (UnsupportedEncodingException e1) {
+		    System.out.println("File: '" + file + "' encoding " +
+				       charSetName + " not supported");
+		    in.close();
+		    continue;
+		} catch (IOException e) {
+		    if (debugFlag) e.printStackTrace();
+		    System.out.println("I/O exception occurred in file '" + sourcepath+file + "'");
+		    in.close();
+		    continue;
+		}
+	    }
+	}
+	parseTime = System.currentTimeMillis() - startTime;
+
+	// show some final statistics
+
+	compileTime = System.currentTimeMillis() - startTime - parseTime;
+	if (verbose != null) {
+	    verbose.println("        Parse time: " + (float)parseTime / 1000.0 + " s");
+	}
+	indexBuilder.close();
+    }
+
+  
+
+    /**
+     * This method invokes the indexerKit to initiate parsing.  In the 
+     * case where a ChangedCharSetException is thrown this exception
+     * will contain the new CharSet.  Therefore the parse() operation
+     * is then restarted after building a new Reader with the new charset.
+     *
+     * @param the inputstream to use.
+     * @param the document to load.
+     *
+     */
+    void parseFile(InputStream in, String file, boolean ignoreCharset) throws IOException {
+	try {
+	    kit.parse(new InputStreamReader(in, charSetName), file, 
+		      ignoreCharset, indexBuilder, config);
+	} catch (com.sun.java.help.search.ChangedCharSetException e1) {
+	    String charSetSpec = e1.getCharSetSpec();
+	    if (e1.keyEqualsCharSet()) {
+		charSetName = charSetSpec;
+	    } else {
+		setCharsetFromContentTypeParameters(charSetSpec);
+	    }
+	    in.close();
+	    URL url = new URL("file", "", sourcepath+file);
+	    in = url.openStream();
+	    parseFile(in, file, true);
+	}
+    }
+
+
+    public Vector loadFiles (String file, Vector files) {
+	File tstfile = new File (file);
+	if (tstfile.isDirectory()) {
+	    String list[] = tstfile.list();
+	    for (int i=0; i < list.length; i++) {
+		files = loadFiles (tstfile.getPath() + 
+				   File.separator +
+				   list[i], files);
+	    }
+	} else {
+	    files.addElement(file);
+	}
+	return files;
+    }
+
+    /**
+     * Shows the usage message.
+     **/
+
+    public void showUsage() {
+	System.out.println(" Usage:   java JavaHelp.Index options file ...");
+	System.out.println(" Options: -c file   config file");
+	System.out.println("          -db file  generated database file name");
+	System.out.println("          -verbose  verbose documentation");
+	System.out.println("          -nostopwords ignore stop words");
+	System.out.println("          -locale language_country_variant");
+	System.out.println("          -logfile log file name");
+	System.out.println("Note: config file composition:");
+	System.out.println("          IndexRemove /public_html/JavaHelp/demo");
+	System.out.println("          IndexPrepend ..");
+	System.out.println("          StopWords word1 ... wordN");
+	System.out.println("          StopWordsFile stopWordFileName");
+	System.out.println("          File /public_html/JavaHelp/demo/first.html");
+	System.out.println("          File=/public_html/JavaHelp/demo/second.html");
+	System.out.println("          ...");
+    }
+
+    /**
+     * Current content binding of the indexer.
+     */
+    private IndexerKit kit;
+
+    /**
+     * Table of registered type handlers for this indexer.
+     */
+    private Hashtable typeHandlers;
+
+    private String defaultCharSetName = "ISO8859_1";
+    private String charSetName;
+    private String defaultLang = Locale.getDefault().toString();
+    private String lang;
+
+
+    /*
+     * Private AppContext keys for this class's static variables.
+     */
+    private static final Hashtable kitRegistry = new Hashtable();
+    private static final Hashtable kitTypeRegistry = new Hashtable();
+    private static final Hashtable kitLoaderRegistry = new Hashtable();
+
+    static {
+        // set the default bindings
+        registerIndexerKitForContentType("text/plain",
+					 "com.sun.java.help.search.PlainTextIndexerKit",
+					 null);
+	registerIndexerKitForContentType("text/html", 
+					 "com.sun.java.help.search.HTMLIndexerKit",
+					 null);
+
+    }
+
+    
+    /**
+     * Sets the type of content for the current document that this indexer
+     * handles.  This calls <code>getIndexerKitForContentType</code>.
+     * <p>
+     * If there is a charset definition specified as a parameter
+     * of the content type specification, it will be used when
+     * loading input streams using the associated IndexerKit.
+     * For example if the type is specified as 
+     * <code>text/html; charset=EUC-JP</code> the content
+     * will be loaded using the IndexerKit registered for
+     * <code>text/html</code> and the Reader provided to
+     * the IndexerKit to load unicode into the document will
+     * use the <code>EUC-JP</code> charset for translating
+     * to unicode.
+     * 
+     * @param type the non-null mime type for the content editing
+     *   support.
+     */
+    public final void setContentType(String type) {
+	// Set a charSetName to default incase it isn't defined
+	charSetName = defaultCharSetName;
+	// Set the lang to default lang incase it isn't defined
+	lang = defaultLang;
+
+	debug ("type=" + type);
+	// The type could have optional info is part of it,
+	// for example some charset info.  We need to strip that
+	// of and save it.
+	int parm = type.indexOf(";");
+	if (parm > -1) {
+	    // Save the paramList.
+	    String paramList = type.substring(parm);
+	    // update the content type string.
+	    type = type.substring(0, parm).trim();
+	    // Set the charset name from the paramlist
+	    setCharsetFromContentTypeParameters(paramList);
+	}
+        if ((kit == null) || (! type.equals(kit.getContentType()))) {
+            IndexerKit k = getIndexerKitForContentType(type);
+            if (k != null) {
+		kit = k;
+            }
+        }
+	kit.setLocale(lang);
+    }
+
+    /**
+     * This method get's the charset information specified as part
+     * of the content type in the http header information.
+     */
+    private void setCharsetFromContentTypeParameters(String paramlist) {
+	String charset = null;
+	try {
+	    // paramlist is handed to us with a leading ';', strip it.
+	    int semi = paramlist.indexOf(';');
+	    if (semi > -1 && semi < paramlist.length()-1) {
+		paramlist = paramlist.substring(semi + 1);
+	    }
+
+	    if (paramlist.length() > 0) {
+		// parse the paramlist into attr-value pairs & get the
+		// charset pair's value
+		HeaderParser hdrParser = new HeaderParser(paramlist);
+		charset = hdrParser.findValue("charset");
+		if (charset != null) {
+		    charSetName = charset;
+		}
+	    }
+	}
+	catch (IndexOutOfBoundsException e) {
+	    // malformed parameter list, use charset we have
+	}
+	catch (NullPointerException e) {
+	    // malformed parameter list, use charset we have
+	}
+	catch (Exception e) {
+	    // malformed parameter list, use charset we have; but complain
+	    System.err.println("Indexer.getCharsetFromContentTypeParameters failed on: " + paramlist);
+	    e.printStackTrace();
+	}
+    }
+
+    /**
+     * Fetches the indexer kit to use for the given type
+     * of content.  This is called when a type is requested
+     * that doesn't match the currently installed type.
+     * If the component doesn't have an IndexerKit registered
+     * for the given type, it will try to create an 
+     * IndexerKit from the default IndexerKit registry.
+     * If that fails, a PlainIndexerKit is used on the
+     * assumption that all text documents can be represented
+     * as plain text.
+     * <p>
+     * This method can be reimplemented to use some
+     * other kind of type registry.  This can
+     * be reimplemented to use the Java Activation
+     * Framework for example.
+     *
+     * @param type the non-null content type
+     * @return the indexer kit
+     */  
+    public IndexerKit getIndexerKitForContentType(String type) {
+        if (typeHandlers == null) {
+            typeHandlers = new Hashtable(3);
+        }
+        IndexerKit k = (IndexerKit) typeHandlers.get(type);
+        if (k == null) {
+            k = createIndexerKitForContentType(type);
+            if (k != null) {
+                setIndexerKitForContentType(type, k);
+            }
+        }
+        if (k == null) {
+            k = new DefaultIndexerKit();
+	    setIndexerKitForContentType(type, k);
+        }
+        return k;
+    }
+
+    /**
+     * Directly set the indexer kit to use for the given type.
+     *
+     * @param type the non-null content type
+     * @param k the indexer kit to be set
+     */
+    public void setIndexerKitForContentType(String type, IndexerKit k) {
+        if (typeHandlers == null) {
+            typeHandlers = new Hashtable(3);
+        }
+        typeHandlers.put(type, k);
+    }
+
+    /**
+     * Create a handler for the given type from the default registry
+     * of indexer kits.  The registry is created if necessary.  An attempt
+     * is made to dynamically load the prototype of the given kit.  If
+     * successful it is cloned and returned.
+     *
+     * @param type the content type
+     * @return the indexer kit, or null if one cannot be created
+     */
+    public static IndexerKit createIndexerKitForContentType(String type) {
+	debug ("Getting IndexerKit for " + type);
+        IndexerKit k = null;
+	k = (IndexerKit) kitRegistry.get(type);
+        if (k == null) {
+            // try to dynamically load the support 
+            String classname = (String) kitTypeRegistry.get(type);
+	    ClassLoader loader = (ClassLoader) kitLoaderRegistry.get(type);
+	    try {
+		Class c;
+		if (loader != null) {
+		    c = loader.loadClass(classname);
+		} else {
+		    c = Class.forName(classname);
+		}
+                k = (IndexerKit) c.newInstance();
+                kitRegistry.put(type, k);
+            } catch (Throwable e) {
+                if (debugFlag) e.printStackTrace();
+                k = null;
+            }
+        }
+
+        // create a copy of the prototype or null if there
+        // is no prototype.
+        if (k != null) {
+            return (IndexerKit) k.clone();
+        }
+        return null;
+    }
+
+    /**
+     * Establishes the default bindings of type to name.  
+     * The class will be dynamically loaded later when actually
+     * needed, and can be safely changed before attempted uses
+     * to avoid loading unwanted classes.
+     *
+     * @param type the non-null content type
+     * @param classname the class to load later
+     */
+    public static void registerIndexerKitForContentType(String type, String classname, ClassLoader loader) {
+        kitTypeRegistry.put(type, classname);
+	if (loader != null) {
+	    kitLoaderRegistry.put(type, loader);
+	}
+    }
+
+
+    /**
+     * For printf debugging.
+     */
+    private static boolean debugFlag = false;
+    private static void debug(String str) {
+        if( debugFlag ) {
+            System.out.println("Indexer: " + str);
+        }
+    }
+}
diff --git a/jhMaster/JSearch/indexer/com/sun/java/help/search/PlainTextIndexerKit.java b/jhMaster/JSearch/indexer/com/sun/java/help/search/PlainTextIndexerKit.java
new file mode 100644
index 0000000000000000000000000000000000000000..b2881d4b2d3be57075080fcaf6af94b9b93d51bc
--- /dev/null
+++ b/jhMaster/JSearch/indexer/com/sun/java/help/search/PlainTextIndexerKit.java
@@ -0,0 +1,129 @@
+/*
+ * @(#)PlainTextIndexerKit.java	1.3 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @(#) PlainTextIndexerKit.java 1.3 - last change made 10/30/06
+ */
+
+package com.sun.java.help.search;
+
+import java.io.*;
+import java.util.Locale;
+import java.text.*;
+import javax.help.search.IndexerKit;
+import javax.help.search.IndexBuilder;
+import javax.help.search.ConfigFile;
+
+/**
+ * This is the set of things needed by an indexing object
+ * to be a reasonably functioning indexer for some <em>type</em>
+ * of text document.  This implementation provides a default
+ * implementation which treats text as plain text 
+ *
+ * @author  Roger D. Brinkley
+ * @version %I	%G
+ */
+public class PlainTextIndexerKit extends DefaultIndexerKit {
+
+    public PlainTextIndexerKit() {
+	locale = Locale.getDefault();
+    }
+
+    /**
+     * Creates a copy of the indexer kit.  This
+     * allows an implementation to serve as a prototype
+     * for others, so that they can be quickly created.
+     *
+     * @return the copy
+     */
+    public Object clone() {
+        return new PlainTextIndexerKit();
+    }
+
+    /**
+     * Gets the MIME type of the data that this
+     * kit represents support for.  The default
+     * is <code>text/plain</code>.
+     *
+     * @return the type
+     */
+    public String getContentType() {
+        return "text/plain";
+    }
+
+    /**
+     * Inserts content from the given stream, which will be 
+     * treated as plain text.
+     * 
+     * @param in  The stream to read from
+     * @param file The file name being parsed
+     * @param ignoreCharset Ignore the CharacterSet when parsing
+     * @param builder The IndexBuilder for the full text insertion.
+     * @param config The indexer configuration information
+     * @exception IOException on any I/O error
+     */
+    public void parse(Reader in, String file, boolean ignoreCharset,
+		      IndexBuilder builder, 
+		      ConfigFile config) throws IOException 
+    {
+	debug ("parsing " + file);
+			  
+	this.builder = builder;
+	this.config = config;
+	this.file = file;
+	documentStarted = false;
+	int currentPos = 1;
+
+        char[] buff = new char[4096];
+        int nch;
+        while ((nch = in.read(buff, 0, buff.length)) != -1) {
+	    currentPos = parseIntoTokens(new String(buff), currentPos);
+        }
+
+	try {
+	    storeTitle("No Title");
+	    endStoreDocument();
+	} catch (Exception e2) {
+	    throw new IOException("Can't store title");
+	}
+
+	this.builder = null;
+	this.config = null;
+    }
+
+
+    /**
+     * Debug code
+     */
+
+    private boolean debugFlag=false;
+    private void debug(String msg) {
+        if (debugFlag) {
+            System.err.println("PlainTextIndexerKit: "+msg);
+        }
+    }
+}
diff --git a/jhMaster/JSearch/indexer/com/sun/java/help/search/package.html b/jhMaster/JSearch/indexer/com/sun/java/help/search/package.html
new file mode 100644
index 0000000000000000000000000000000000000000..1a412d81375060d24c52b69d47cb8a551f0a4b1d
--- /dev/null
+++ b/jhMaster/JSearch/indexer/com/sun/java/help/search/package.html
@@ -0,0 +1,56 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<!--
+
+  @(#)package.html 1.1 10/15/98
+
+  Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+  DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+  This code is free software; you can redistribute it and/or modify it
+  under the terms of the GNU General Public License version 2 only, as
+  published by the Free Software Foundation.  Sun designates this
+  particular file as subject to the "Classpath" exception as provided
+  by Sun in the LICENSE file that accompanied this code.
+ 
+  This code is distributed in the hope that it will be useful, but WITHOUT
+  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+  version 2 for more details (a copy is included in the LICENSE file that
+  accompanied this code).
+ 
+  You should have received a copy of the GNU General Public License version
+  2 along with this work; if not, write to the Free Software Foundation,
+  Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ 
+  Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+  CA 95054 USA or visit www.sun.com if you need additional information or
+  have any questions.
+
+-->
+
+</head>
+<body bgcolor="white">
+
+Implementation classes for the default Search builder using in the
+reference implementation of JavaHelp.
+
+<p>
+<em>Note:</em>We have not yet finalized the location for these classes.
+
+<!--
+<H2>Package Specification</H2>
+Link to updated API specification to be added here.
+-->
+
+<H2>Related Documentation</H2>
+
+<P>
+For overviews, tutorials, examples, guides, tool support,
+and other documentation,
+please see
+<A HREF="http://java.sun.com/products/javahelp/">the JavaHelp home page</A>
+
+  </body>
+</html>
diff --git a/jhMaster/JSearch/jhsearch.bat b/jhMaster/JSearch/jhsearch.bat
new file mode 100644
index 0000000000000000000000000000000000000000..59579ada0f1f091467b07feacf26c4598e3afd48
--- /dev/null
+++ b/jhMaster/JSearch/jhsearch.bat
@@ -0,0 +1,46 @@
+@echo off
+
+REM
+REM @(#)jhsearch.bat	1.5 06/10/30
+REM 
+REM Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+REM DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+REM 
+REM This code is free software; you can redistribute it and/or modify it
+REM under the terms of the GNU General Public License version 2 only, as
+REM published by the Free Software Foundation.  Sun designates this
+REM particular file as subject to the "Classpath" exception as provided
+REM by Sun in the LICENSE file that accompanied this code.
+REM 
+REM This code is distributed in the hope that it will be useful, but WITHOUT
+REM ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+REM FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+REM version 2 for more details (a copy is included in the LICENSE file that
+REM accompanied this code).
+REM 
+REM You should have received a copy of the GNU General Public License version
+REM 2 along with this work; if not, write to the Free Software Foundation,
+REM Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+REM 
+REM Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+REM CA 95054 USA or visit www.sun.com if you need additional information or
+REM have any questions.
+REM
+
+rem Run the JHSearch
+rem @(#)jhsearch.bat 1.3 07/14/98
+
+if ."%JSHOME%".==."". goto nojhhome
+goto runnit
+:nojhhome
+echo The environment variable JSHOME has not been set
+goto done
+echo 
+:runnit
+@echo on
+set CLASSPATH=%JSHOME%\lib\jsearch.jar
+java com.sun.java.help.search.QueryEngine %1
+@echo off
+
+:done
+
diff --git a/jhMaster/JSearch/misc/GNUmakefile b/jhMaster/JSearch/misc/GNUmakefile
new file mode 100644
index 0000000000000000000000000000000000000000..731417a370a1b0a200c93492f08fa844fccc966b
--- /dev/null
+++ b/jhMaster/JSearch/misc/GNUmakefile
@@ -0,0 +1,69 @@
+#
+# @(#)GNUmakefile	1.12 06/10/30
+# 
+# Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+# 
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.  Sun designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Sun in the LICENSE file that accompanied this code.
+# 
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+# 
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+# 
+# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+# CA 95054 USA or visit www.sun.com if you need additional information or
+# have any questions.
+#
+
+.SUFFIXES:
+.SUFFIXES: .java .class
+
+JHHOMEWS=../../JavaHelp
+VPATH = $(JHHOMEWS)/src/impl:$(JHHOMEWS)/src/new
+
+SEARCH_SRC=ConfigFile.java \
+	IndexBuilder.java \
+	IndexerKit.java \
+	SearchEngine.java \
+	SearchEvent.java \
+	SearchItem.java \
+	SearchListener.java \
+	SearchQuery.java
+
+SEARCH_CLASSES=$(SEARCH_SRC:%.java=classes/javax/help/search/%.class)
+
+OTHER_SRC=javax/help/event/EventListenerList.java \
+	javax/help/HelpUtilities.java
+
+OTHER_CLASSES=$(OTHER_SRC:%.java=classes/%.class)
+
+IMPL_SRC:=com/sun/java/help/impl/HeaderParser.java
+IMPL_CLASSES=$(IMPL_SRC:%.java=classes/%.class)
+
+ALL_CLASSES=$(SEARCH_CLASSES) $(IMPL_CLASSES) $(OTHER_CLASSES)
+
+
+jar:	../lib/jsearch-misc.jar
+
+../lib/jsearch-misc.jar:  classes $(ALL_CLASSES)
+	cd classes ; \
+	jar cf ../../lib/jsearch-misc.jar javax com
+
+classes/%.class: %.java
+	javac -d classes -classpath ../../JavaHelp/src/impl:../../JavaHelp/src/new $<
+
+classes:
+	mkdir classes
+
+clean:
+	$(RM) -rf classes
diff --git a/jhMaster/JavaHelp/doc/css/default.css b/jhMaster/JavaHelp/doc/css/default.css
new file mode 100644
index 0000000000000000000000000000000000000000..16a11734f93021aeea3da4fdf4eafe0d2a244f51
--- /dev/null
+++ b/jhMaster/JavaHelp/doc/css/default.css
@@ -0,0 +1,259 @@
+/*
+ * @(#)default.css	1.37 98/10/17
+ *
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+body  {font-size: 14pt;
+       font-family: SansSerif;
+       margin-left: 0;
+       margin-right: 0;
+       color: black}
+
+p   {font-size: medium;
+     font-weight: normal;
+     margin-top: 15}
+
+h1  {font-size: x-large;
+     font-weight: bold;
+     margin-top: 10;
+     margin-bottom: 10}
+
+h2 {font-size: large;
+    font-weight: bold;
+    margin-top: 10;
+    margin-bottom: 10}
+
+h3 {font-size: medium;
+    font-weight: bold;
+    margin-top: 10;
+    margin-bottom: 10}
+
+h4 {font-size: small;
+    font-weight: bold;
+    margin-top: 10;
+    margin-bottom: 10}
+
+h5 {font-size: x-small;
+    font-weight: bold;
+    margin-top: 10;
+    margin-bottom: 10}
+
+h6 {font-size: xx-small;
+    font-weight: bold;
+    margin-top: 10;
+    margin-bottom: 10}
+
+li p {margin-top: 0;
+    margin-bottom: 0}
+
+menu li p {margin-top: 0;
+    margin-bottom: 0}
+
+menu li {margin-left: 0;
+    margin-right: 0;
+    margin-top: 0;
+    margin-bottom: 0}
+
+menu {margin-left: 40;
+    margin-top: 10;
+    margin-bottom: 10}
+
+dir li p {margin-top: 0;
+    margin-bottom: 0}
+
+dir li {margin-left: 0;
+    margin-right: 0;
+    margin-top: 0;
+    margin-bottom: 0}
+
+dir {margin-left: 40;
+    margin-top: 10;
+    margin-bottom: 10}
+
+dd p {margin-left: 40;
+    margin-top: 0;
+    margin-bottom: 0}
+
+dt {margin-top: 0;
+    margin-bottom: 0}
+
+dl {margin-left: 10;
+    margin-top: 10;
+    margin-bottom: 10}
+
+ol li {margin-left: 0;
+    margin-right: 0;
+    margin-top: 0;
+    margin-bottom: 0}
+
+ol {
+    margin-top: 10;
+    margin-bottom: 10;
+    margin-left: 50;
+    list-style-type: decimal
+}
+
+ol li p {margin-top: 0;
+    margin-bottom:0}
+
+ul li {margin-left: 0;
+    margin-right: 0;
+    margin-top: 0;
+    margin-bottom: 0}
+
+ul {margin-top: 10;
+    margin-bottom: 10;
+    margin-left: 50;
+    list-style-type: disc;
+    -bullet-gap: 10}
+
+ul li ul li {margin-left: 0;
+    margin-right: 0;
+    margin-top: 0;
+    margin-bottom: 0}
+
+ul li ul {list-style-type: circle;
+    margin-left: 25}
+
+ul li ul li ul li {margin-left: 0;
+    margin-right: 0;
+    margin-top: 0;
+    margin-bottom: 0}
+
+ul li ul li ul {list-style-type: square;
+    margin-left: 25}
+
+ul li menu {list-style-type: circle;
+    margin-left: 25}
+
+ul li p {margin-top: 0;
+    margin-bottom:0}
+
+a {color: blue;
+   text-decoration: underline}
+
+big {font-size: x-large}
+
+small {font-size: x-small}
+
+samp {font-size: small;
+      font-family: Monospaced}
+
+cite {font-style: italic}
+
+code {font-size: small;
+      font-family: Monospaced}
+
+dfn {font-style: italic}
+
+em {font-style: italic}
+
+i  {font-style: italic}
+
+b  {font-weight: bold}
+
+kbd {font-size: small;
+     font-family: Monospaced}
+
+s {text-decoration: line-through}
+
+strike {text-decoration: line-through}
+
+strong {font-weight: bold}
+
+sub {vertical-align: sub}
+
+sup {vertical-align: sup}
+
+tt {font-family: Monospaced}
+
+u {text-decoration: underline}
+
+var {font-weight: bold;
+     font-style: italic}
+
+table {
+	border-color: Gray;
+	border-style: outset;
+	margin-top: 5;
+       	margin-bottom: 5;
+       	margin-left: 5;
+	margin-right: 5
+}
+
+td {
+	border-color: Gray;
+	border-style: inset;
+	padding-left: 1;
+	padding-right: 1;
+	padding-top: 1;
+	padding-bottom: 1
+}
+
+th {
+	border-color: Gray;
+	border-style: inset;
+	padding-left: 1;
+	padding-right: 1;
+	padding-top: 1;
+	padding-bottom: 1
+}
+
+td p {
+	margin-top: 0;   
+	padding-top: 2;
+	padding-bottom: 2;
+	padding-left: 2;
+	padding-right: 2
+}
+
+th p { 
+	margin-top: 0;   
+	font-weight: bold;
+	padding-top: 2;
+	padding-bottom: 2;
+	padding-left: 2;
+	padding-right: 2
+}
+
+address {
+	color: blue;
+	font-style: italic
+}
+
+blockquote {
+	margin-top: 5;
+	margin-bottom: 5;
+	margin-left: 35;
+	margin-right: 35
+}
+
+center {text-align: center}
+
+pre {margin-top: 5;
+     margin-bottom: 5;
+     font-family: Monospaced}
+
+pre p {margin-top: 0}
diff --git a/jhMaster/JavaHelp/doc/jhug/GNUmakefile b/jhMaster/JavaHelp/doc/jhug/GNUmakefile
new file mode 100644
index 0000000000000000000000000000000000000000..b501765657d1d9ba961a72fcff37f8e4f929e16a
--- /dev/null
+++ b/jhMaster/JavaHelp/doc/jhug/GNUmakefile
@@ -0,0 +1,116 @@
+#
+# @(#)GNUmakefile	1.22 06/10/30
+# 
+# Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+# 
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.  Sun designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Sun in the LICENSE file that accompanied this code.
+# 
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+# 
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+# 
+# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+# CA 95054 USA or visit www.sun.com if you need additional information or
+# have any questions.
+#
+
+# @(#)GNUmakefile	1.10 97/06/05
+#
+# Makefile for use on Solaris using gnumake.
+# It assumes JavaHelp has been built previously
+# Just builds the search index for the user's guide
+# Then build the jhug.pdf file. 
+# Note: You must set your path correctly for html2ps, perl, and distill
+#       For building at JavaSoft this means making sure path includes
+#       /net/suntools.sfbay/export/tools/sparc/bin 
+
+JHHOME = ../../javahelp/
+INDEXER=$(JHHOME)/bin/jhindexer
+
+JHUG_CONTENT_FILES = jhug.html \
+	release/release.html \
+	release/contents.html \
+	release/requirements.html \
+	release/changes.html \
+	release/demos.html \
+	release/helpsets.html \
+	release/libraries.html \
+	release/limitations.html \
+	release/file_list.html \
+	overview/overview.html \
+	overview/intro.html \
+	overview/features.html \
+	overview/scenarios.html \
+	overview/invocation.html \
+	overview/deploy.html \
+	overview/search.html \
+	overview/jcomp.html \
+	author/author.html \
+	author/viewing.html \
+	author/accessibility.html \
+	author/setup.html \
+	author/helpset.html \
+	author/map.html \
+	author/jar.html \
+	author/toc.html \
+	author/index.html \
+	author/csh.html \
+	author/search.html \
+	author/searchdb.html \
+	author/jhindexer.html \
+	author/jhsearch.html \
+	author/popup.html \
+	author/merge.html \
+	dev/dev.html \
+	dev/basics.html \
+	dev/csh.html \
+      dev/dynamicmerge.html \
+	dev/embed.html \
+	dev/lwcomp.html \
+	dev/serverhlp.html \
+	locale/loc.html \
+	locale/loc_pres.html \
+	locale/loc_helpset.html \
+	locale/loc_xml.html \
+	locale/loc_html.html \
+	locale/loc_font.html \
+	locale/loc_search.html\
+      jhugIndex.html 
+
+JHUG_SEARCH_FILES = \
+	JavaHelpSearch/DOCS \
+	JavaHelpSearch/DOCS.TAB \
+	JavaHelpSearch/OFFSETS \
+	JavaHelpSearch/POSITIONS \
+	JavaHelpSearch/SCHEMA \
+	JavaHelpSearch/TMAP
+
+JHUG_SOURCE_FILES = \
+	$(JHUG_CONTENT_FILES) \ 
+
+all: $(JHUG_SEARCH_FILES)
+
+clean:
+	rm -f $(JHUG_SEARCH_FILES)
+
+$(JHUG_SEARCH_FILES): $(JHUG_CONTENT_FILES)
+	@rm -f $(JHUG_SEARCH_FILES)
+	@mkdir -p JavaHelpSearch
+	ksh $(INDEXER) -verbose $(JHUG_CONTENT_FILES)
+
+# jhug.pdf: $(JHUG_CONTENT_FILES)
+#	@rm -f jhug.pdf
+#	perl5 ../../build/tools/html2ps -u -t -C hb $(JHUG_CONTENT_FILES) > jhug.ps
+#	distill jhug.ps
+#	$(RM) jhug.ps
diff --git a/jhMaster/JavaHelp/doc/public-spec/V2.0/GNUmakefile b/jhMaster/JavaHelp/doc/public-spec/V2.0/GNUmakefile
new file mode 100644
index 0000000000000000000000000000000000000000..b207cb8d3209a041c2833f63d59231da5868a828
--- /dev/null
+++ b/jhMaster/JavaHelp/doc/public-spec/V2.0/GNUmakefile
@@ -0,0 +1,43 @@
+#
+# @(#)GNUmakefile	1.3 06/10/30
+# 
+# Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+# 
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.  Sun designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Sun in the LICENSE file that accompanied this code.
+# 
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+# 
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+# 
+# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+# CA 95054 USA or visit www.sun.com if you need additional information or
+# have any questions.
+#
+
+#  demo.jar is the JAR that defines the application
+SPEC = JavaHelp_V2_0_Specification.pdf
+
+FILES = JavaHelp_V2_0_Specification.fm \
+        bookTOC.fm \
+        contents.fm \
+        cover.fm \
+        credits.fm
+
+all: $(SPEC)
+
+clean:
+	rm -rf $(SPEC)
+
+$(SPEC): $(FILES)
+	/usr/dist/share/framemaker/bin/fmbatch -v createbook.txt
diff --git a/jhMaster/JavaHelp/javahelp/bin/GNUmakefile b/jhMaster/JavaHelp/javahelp/bin/GNUmakefile
new file mode 100644
index 0000000000000000000000000000000000000000..ee8f4940e0d080305253a489b078e2dc303140dd
--- /dev/null
+++ b/jhMaster/JavaHelp/javahelp/bin/GNUmakefile
@@ -0,0 +1,50 @@
+#
+# @(#)GNUmakefile	1.2 06/10/30
+# 
+# Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+# 
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.  Sun designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Sun in the LICENSE file that accompanied this code.
+# 
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+# 
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+# 
+# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+# CA 95054 USA or visit www.sun.com if you need additional information or
+# have any questions.
+#
+
+# @(#)GNUmakefile	1.10 97/06/05
+#
+# Makefile for use on Solaris using gnumake.
+
+# apiviewer.jar has launcher code. 
+JHINDEXER_JAR = jhindexer.jar
+JHSEARCH_JAR = jhsearch.jar
+
+CP=/bin/cp -f
+
+all: $(JHINDEXER_JAR) $(JHSEARCH_JAR)
+
+clean:
+	rm -f -r $(JHINDEXER_JAR) $(JHSEARCH_JAR)
+
+$(JHINDEXER_JAR):
+	@rm -f $(JHINDEXER_JAR)
+	jar cmf manifest_jhindexer $(JHINDEXER_JAR)
+
+$(JHSEARCH_JAR):
+	@rm -f $(JHSEARCH_JAR)
+	jar cmf manifest_jhsearch $(JHSEARCH_JAR)
+
diff --git a/jhMaster/JavaHelp/javahelp/bin/jhindexer b/jhMaster/JavaHelp/javahelp/bin/jhindexer
new file mode 100644
index 0000000000000000000000000000000000000000..e84a1b2de1e412be2cf73f6e779e5ceb95fc35aa
--- /dev/null
+++ b/jhMaster/JavaHelp/javahelp/bin/jhindexer
@@ -0,0 +1,49 @@
+#! /bin/sh
+# This builds a search database 
+
+# Cygwin support.  $cygwin _must_ be set to either true or false.
+case "`uname`" in
+  CYGWIN*) cygwin=true ;;
+  *) cygwin=false ;;
+esac
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin; then
+  [ -n "$JAVAHELP_HOME" ] &&
+    JAVAHELP_HOME=`cygpath --unix "$JAVAHELP_HOME"`
+fi
+
+if [ "$JAVAHELP_HOME" = "" ] ; then
+  # try to find jhindexer
+  if [ -d /opt/javahelp ] ; then 
+    JAVAHELP_HOME=/opt/javahelp
+  fi
+
+  if [ -d ${HOME}/opt/jhindexer ] ; then 
+    JAVAHELP_HOME=${HOME}/opt/javahelp
+  fi
+
+  ## resolve links - $0 may be a link to javahelp's home
+  PRG=$0
+  progname=`basename $0`
+  
+  while [ -h "$PRG" ] ; do
+    ls=`ls -ld "$PRG"`
+    link=`expr "$ls" : '.*-> \(.*\)$'`
+    if expr "$link" : '.*/.*' > /dev/null; then
+	PRG="$link"
+    else
+	PRG="`dirname $PRG`/$link"
+    fi
+  done
+  
+  JAVAHELP_HOME=`dirname "$PRG"`/../..
+
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin; then
+  JAVAHELP_HOME=`cygpath --path --windows "$JAVAHELP_HOME"`
+fi
+
+java -jar $JAVAHELP_HOME/javahelp/bin/jhindexer.jar "$@"
diff --git a/jhMaster/JavaHelp/javahelp/bin/jhindexer.bat b/jhMaster/JavaHelp/javahelp/bin/jhindexer.bat
new file mode 100644
index 0000000000000000000000000000000000000000..454af485d9e476c1329001d945bd7b02128d7cd9
--- /dev/null
+++ b/jhMaster/JavaHelp/javahelp/bin/jhindexer.bat
@@ -0,0 +1,75 @@
+@echo off
+
+REM
+REM @(#)jhindexer.bat	1.20 06/10/30
+REM 
+REM Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+REM DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+REM 
+REM This code is free software; you can redistribute it and/or modify it
+REM under the terms of the GNU General Public License version 2 only, as
+REM published by the Free Software Foundation.  Sun designates this
+REM particular file as subject to the "Classpath" exception as provided
+REM by Sun in the LICENSE file that accompanied this code.
+REM 
+REM This code is distributed in the hope that it will be useful, but WITHOUT
+REM ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+REM FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+REM version 2 for more details (a copy is included in the LICENSE file that
+REM accompanied this code).
+REM 
+REM You should have received a copy of the GNU General Public License version
+REM 2 along with this work; if not, write to the Free Software Foundation,
+REM Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+REM 
+REM Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+REM CA 95054 USA or visit www.sun.com if you need additional information or
+REM have any questions.
+REM
+
+
+if not "%OS%"=="Windows_NT" goto win9xStart
+:winNTStart
+@setlocal
+
+rem %~dp0 is name of current script under NT
+set DEFAULT_JAVAHELP_HOME=%~dp0
+
+rem : operator works similar to make : operator
+set DEFAULT_JAVAHELP_HOME=%DEFAULT_JAVAHELP_HOME:\javahelp\bin\=%
+
+if %JAVAHELP_HOME%a==a set JAVAHELP_HOME=%DEFAULT_JAVAHELP_HOME%
+set DEFAULT_JAVAHELP_HOME=
+goto doneStart
+
+:win9xStart
+:doneStart
+rem This label provides a place for NT handling to skip to.
+
+rem find JAVAHELP_HOME
+if not "%JAVAHELP_HOME%"=="" goto runjhindexer
+
+rem check for JavaHelp in Program Files on system drive
+if not exist "%SystemDrive%\Program Files\jh" goto checkSystemDrive
+set JAVAHELP_HOME=%SystemDrive%\Program Files\jh
+goto checkJava
+
+:checkSystemDrive
+rem check for JavaHelp in root directory of system drive
+if not exist "%SystemDrive%\jh" goto noJavaHelpHome
+set JAVA_HOME=%SystemDrive%\jh
+goto runjhindexer
+
+:noJavaHelpHome
+echo JAVAHELP_HOME is not set and JavaHelp could not be located. Please set JAVAHELP_HOME.
+goto end
+
+:runjhindexer
+java -jar %JAVAHELP_HOME%\javahelp\bin\jhindexer.jar %1 %2 %3 %4 %5 %6 %7 %8 %9 
+
+if not "%OS%"=="Windows_NT" goto mainEnd
+:winNTend
+@endlocal
+
+:mainEnd
+
diff --git a/jhMaster/JavaHelp/javahelp/bin/jhsearch b/jhMaster/JavaHelp/javahelp/bin/jhsearch
new file mode 100644
index 0000000000000000000000000000000000000000..67e050b8c50c5f2db8d27db16c2c0a9696cf1d14
--- /dev/null
+++ b/jhMaster/JavaHelp/javahelp/bin/jhsearch
@@ -0,0 +1,49 @@
+#! /bin/sh
+# This searches a search database.  Argument is the database directory
+
+# Cygwin support.  $cygwin _must_ be set to either true or false.
+case "`uname`" in
+  CYGWIN*) cygwin=true ;;
+  *) cygwin=false ;;
+esac
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin; then
+  [ -n "$JAVAHELP_HOME" ] &&
+    JAVAHELP_HOME=`cygpath --unix "$JAVAHELP_HOME"`
+fi
+
+if [ "$JAVAHELP_HOME" = "" ] ; then
+  # try to find jhindexer
+  if [ -d /opt/javahelp ] ; then 
+    JAVAHELP_HOME=/opt/javahelp
+  fi
+
+  if [ -d ${HOME}/opt/jhindexer ] ; then 
+    JAVAHELP_HOME=${HOME}/opt/javahelp
+  fi
+
+  ## resolve links - $0 may be a link to javahelp's home
+  PRG=$0
+  progname=`basename $0`
+  
+  while [ -h "$PRG" ] ; do
+    ls=`ls -ld "$PRG"`
+    link=`expr "$ls" : '.*-> \(.*\)$'`
+    if expr "$link" : '.*/.*' > /dev/null; then
+	PRG="$link"
+    else
+	PRG="`dirname $PRG`/$link"
+    fi
+  done
+  
+  JAVAHELP_HOME=`dirname "$PRG"`/../..
+
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin; then
+  JAVAHELP_HOME=`cygpath --path --windows "$JAVAHELP_HOME"`
+fi
+
+java -jar $JAVAHELP_HOME/javahelp/bin/jhsearch.jar "$@"
diff --git a/jhMaster/JavaHelp/javahelp/bin/jhsearch.bat b/jhMaster/JavaHelp/javahelp/bin/jhsearch.bat
new file mode 100644
index 0000000000000000000000000000000000000000..f6ec75d2309a868220769fa60f7be33d271d9378
--- /dev/null
+++ b/jhMaster/JavaHelp/javahelp/bin/jhsearch.bat
@@ -0,0 +1,77 @@
+@echo off
+
+REM
+REM @(#)jhsearch.bat	1.13 06/10/30
+REM 
+REM Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+REM DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+REM 
+REM This code is free software; you can redistribute it and/or modify it
+REM under the terms of the GNU General Public License version 2 only, as
+REM published by the Free Software Foundation.  Sun designates this
+REM particular file as subject to the "Classpath" exception as provided
+REM by Sun in the LICENSE file that accompanied this code.
+REM 
+REM This code is distributed in the hope that it will be useful, but WITHOUT
+REM ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+REM FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+REM version 2 for more details (a copy is included in the LICENSE file that
+REM accompanied this code).
+REM 
+REM You should have received a copy of the GNU General Public License version
+REM 2 along with this work; if not, write to the Free Software Foundation,
+REM Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+REM 
+REM Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+REM CA 95054 USA or visit www.sun.com if you need additional information or
+REM have any questions.
+REM
+
+
+if not "%OS%"=="Windows_NT" goto win9xStart
+:winNTStart
+@setlocal
+
+rem %~dp0 is name of current script under NT
+set DEFAULT_JAVAHELP_HOME=%~dp0
+
+rem : operator works similar to make : operator
+set DEFAULT_JAVAHELP_HOME=%DEFAULT_JAVAHELP_HOME:\javahelp\bin\=%
+
+if %JAVAHELP_HOME%a==a set JAVAHELP_HOME=%DEFAULT_JAVAHELP_HOME%
+set DEFAULT_JAVAHELP_HOME=
+goto doneStart
+
+:win9xStart
+:doneStart
+rem This label provides a place for NT handling to skip to.
+
+rem find JAVAHELP_HOME
+if not "%JAVAHELP_HOME%"=="" goto runjhsearch
+
+rem check for JavaHelp in Program Files on system drive
+if not exist "%SystemDrive%\Program Files\jh" goto checkSystemDrive
+set JAVAHELP_HOME=%SystemDrive%\Program Files\jh
+goto checkJava
+
+:checkSystemDrive
+rem check for JavaHelp in root directory of system drive
+if not exist "%SystemDrive%\jh" goto noJavaHelpHome
+set JAVA_HOME=%SystemDrive%\jh
+goto runjhsearch
+
+:noJavaHelpHome
+echo JAVAHELP_HOME is not set and JavaHelp could not be located. Please set JAVAHELP_HOME.
+goto end
+
+:runjhsearch
+java -jar %JAVAHELP_HOME%\javahelp\bin\jhsearch.jar %1
+
+if not "%OS%"=="Windows_NT" goto mainEnd
+:winNTend
+@endlocal
+
+:mainEnd
+
+
+
diff --git a/jhMaster/JavaHelp/linuxRPM/GNUmakefile b/jhMaster/JavaHelp/linuxRPM/GNUmakefile
new file mode 100644
index 0000000000000000000000000000000000000000..cb80ebb20bfd02dda7b32ea6f4eb684825e7d9b2
--- /dev/null
+++ b/jhMaster/JavaHelp/linuxRPM/GNUmakefile
@@ -0,0 +1,207 @@
+#
+# @(#)GNUmakefile	1.7 06/11/01
+# 
+# Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+# 
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.  Sun designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Sun in the LICENSE file that accompanied this code.
+# 
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+# 
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+# 
+# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+# CA 95054 USA or visit www.sun.com if you need additional information or
+# have any questions.
+#
+
+# @(#)GNUmakefile	1.7 06/11/01
+# Install for JavaHelp.
+# This is a linux RPM GNUmakefile
+
+JH_NAME=javahelp
+JH_VERSION=2.0
+TEMP_DIR=/tmp/rpm-$(JH_NAME)
+NATIVE_ARCH=i586
+JH_VERSION=2.0
+PKGNAME=SUNWjhrt
+J2SE=j2se
+OPT=j2se/opt
+DJH=j2se/opt/javahelp
+INSTALL=$(PKGNAME)/install
+RELOC=$(PKGNAME)/reloc
+PWD=$(shell pwd)
+OWNERGROUP=$(shell id | cut -f2  -d'(' | cut -f1 -d')') $(shell groups | cut -f1 -d' ')
+PKGPATH=$(PWD)/$(PKGNAME)
+
+JD=../$(JH_NAME)
+TOP=..
+PKGTOP=.
+
+CAT=/bin/cat
+CD=cd
+CHMOD=/bin/chmod
+CP=/bin/cp -p -f
+ECHO=echo
+MKDIR=/bin/mkdir -p
+RM=/bin/rm -f
+RPM=/usr/bin/rpmbuild
+TAR=/bin/tar
+FIND=/usr/bin/find
+MV=/bin/mv -f
+JAR=jar
+
+all: copy prep-RPM build-RPM 
+	echo DONE with RPM!
+
+dirs: $(J2SE) $(OPT) $(DJH)
+
+package: $(PKGPATH) pkginfo proto
+
+copy:
+	$(ECHO) ### Removing old javahelp directories
+	$(RM) -r $(TEMP_DIR)
+	$(MKDIR) -p $(TEMP_DIR)
+	pwd
+	$(ECHO) ### Copying over the jh2.0 image for use with RPM
+	$(CD) .. ;$(TAR) cf - jh$(JH_VERSION) | ( cd $(TEMP_DIR) ; $(TAR) xfBp -)
+###	$(MV) $(TEMP_DIR)/jh$(JH_VERSION) $(TEMP_DIR)/$(JH_NAME)$(JH_VERSION) 
+	$(MKDIR) $(TEMP_DIR)/packages
+	$(MV) $(TEMP_DIR)/jh$(JH_VERSION) $(TEMP_DIR)/packages/javax.help-$(JH_VERSION) 
+	$(FIND) $(TEMP_DIR) -name "*.bat" -print -exec $(RM) {} \;
+###	$(CD) $(TEMP_DIR) ; $(TAR) cf $(JH_NAME)$(JH_VERSION).tar $(JH_NAME)$(JH_VERSION)
+	$(CD) $(TEMP_DIR) ; $(TAR) cf $(JH_NAME)$(JH_VERSION).tar packages
+
+
+clobber:
+	$(RM) -rf j2se
+	$(RM) -rf $(PKGNAME)
+	$(RM) -rf prototype
+	$(RM) -rf pkginfo
+
+
+
+prep-RPM:
+
+	@#subtle: override the sourcedir so that we don't have to copy
+	@#        large binaries around.
+	@# $(ECHO) "%_sourcedir	$(ABS_OUTPUTDIR)" >> $(RPM_MACROFILE)
+	@# $(ECHO) "%_sourcedir	$(TEMP_DIR)" >> $(HOME)/.rpmmacros_jh
+	@# $(ECHO) "%_builddir	$(TEMP_DIR)/BUILD" >> $(RPM_MACROFILE)
+	@# $(ECHO) "%_rpmdir	$(TEMP_DIR)" >> $(RPM_MACROFILE)
+	@#
+	@# generate the gen-rpm-jh.spec file
+	@#
+	$(ECHO) milestone is $(MILESTONE)
+	$(ECHO) ### generate the gen-rpm-jh.spec file
+	$(ECHO) " "  >> $(TEMP_DIR)/gen-rpm-jh.spec
+	$(ECHO) "%define _builddir $(TEMP_DIR)" >> $(TEMP_DIR)/gen-rpm-jh.spec
+	$(ECHO) "%define _sourcedir $(TEMP_DIR)" >> $(TEMP_DIR)/gen-rpm-jh.spec
+	$(ECHO) "%define _rpmdir $(TEMP_DIR)" >> $(TEMP_DIR)/gen-rpm-jh.spec
+	$(ECHO) "%define _tmppath $(TEMP_DIR)" >> $(TEMP_DIR)/gen-rpm-jh.spec
+	$(ECHO) "%define jh_prefix 	/usr/java" >> $(TEMP_DIR)/gen-rpm-jh.spec
+	$(ECHO) "%define jh_tarfile 	javahelp$(VERSION).tar" >> $(TEMP_DIR)/gen-rpm-jh.spec
+	$(ECHO) "%define arch		i586" >> $(TEMP_DIR)/gen-rpm-jh.spec
+	$(ECHO) "%define jh_dir		packages/javax.help-$(JH_VERSION)" >> $(TEMP_DIR)/gen-rpm-jh.spec
+	$(ECHO) "%define jh_name	$(JH_NAME)" >> $(TEMP_DIR)/gen-rpm-jh.spec
+	$(ECHO) "%define jh_version	$(JH_VERSION)" >> $(TEMP_DIR)/gen-rpm-jh.spec
+	@#	$(ECHO) "%define packed_jars	\"$(JRE_PACKED_JARS)\"" >> $(TEMP_DIR)/gen-rpm-jh.spec
+	$(ECHO) " " >> $(TEMP_DIR)/gen-rpm-jh.spec
+	$(ECHO) "Name:	sun-$(JH_NAME)" >> $(TEMP_DIR)/gen-rpm-jh.spec
+	$(ECHO) "Summary: JavaHelp Runtime/Development Environment" >> $(TEMP_DIR)/gen-rpm-jh.spec
+	$(ECHO) "Version:	%{jh_version}" >> $(TEMP_DIR)/gen-rpm-jh.spec
+	$(ECHO) "Release:	fcs" >> $(TEMP_DIR)/gen-rpm-jh.spec
+	$(ECHO) "Copyright:	1994-2004 Sun Microsystems, Inc." >> $(TEMP_DIR)/gen-rpm-jh.spec
+	$(ECHO) "Group:		Java Software Engineering" >> $(TEMP_DIR)/gen-rpm-jh.spec
+	@#	$(ECHO) "Provides: jaxp_parser_impl, xml-commons-apis" >> $(TEMP_DIR)/gen-rpm-jh.spec
+	$(ECHO) "Requires:	glibc >= 2.1.2-11, sh-utils >= 2.0-1, fileutils >= 4.0-8, gawk >= 3.0.4-1, textutils >= 2.0-2" >> $(TEMP_DIR)/gen-rpm-jh.spec
+	$(ECHO) "AutoReqProv:	no" >> $(TEMP_DIR)/gen-rpm-jh.spec
+	$(ECHO) "Url:	http://java.sun.com/products/javahelp" >> $(TEMP_DIR)/gen-rpm-jh.spec
+	$(ECHO) "Vendor:	Sun Microsystems, Inc." >> $(TEMP_DIR)/gen-rpm-jh.spec
+	$(ECHO) "Source:	$(JH_NAME)$(JH_VERSION).tar" >> $(TEMP_DIR)/gen-rpm-jh.spec
+	$(ECHO) "Packager:	Java Software <http://java.sun.com/docs/forms/javahelp-sendusmail.html>" >> \
+		$(TEMP_DIR)/gen-rpm-jh.spec
+	@###$(ECHO) "Buildroot:	$(TEMP_DIR)/rpm-root" >> $(TEMP_DIR)/gen-rpm-jh.spec
+	$(ECHO) "Buildroot:	$(TEMP_DIR)" >> $(TEMP_DIR)/gen-rpm-jh.spec
+	$(ECHO) "Prefix: %{jre_prefix}" >> $(TEMP_DIR)/gen-rpm-jh.spec
+	$(ECHO) " " >> $(TEMP_DIR)/gen-rpm-jh.spec
+	$(ECHO) "%description" >> $(TEMP_DIR)/gen-rpm-jh.spec
+	$(ECHO) -n "The JavaHelp Runtime/Development Environment consists of JavaHelp " >> $(TEMP_DIR)/gen-rpm-jh.spec
+	@#	$(ECHO) -n "virtual machine, the Java platform core classes, " >> $(TEMP_DIR)/gen-rpm-jh.spec
+	@#	$(ECHO) -n "and supporting files. It is the runtime part of " >> $(TEMP_DIR)/gen-rpm-jh.spec
+	$(ECHO) " " >> $(TEMP_DIR)/gen-rpm-jh.spec
+	@#
+	@# add the rest of the template to the spec file...
+	@#
+	$(CAT) rpm-jh.spec >> $(TEMP_DIR)/gen-rpm-jh.spec
+
+build-RPM:
+	@#
+	@# rpm wants to put the .rpm file the _rpmdir/{arch} directory.
+	@#
+	@######-$(MKDIR) $(TEMP_DIR)
+	@# on RH8 rpm builds as user 'rpm'
+	$(CHMOD) 777  $(TEMP_DIR)
+	@# 
+	@# generate the rpm file...
+	@#
+	$(RPM) -bb --buildroot $(TEMP_DIR) --rmsource --target $(NATIVE_ARCH)-Sun-Linux $(TEMP_DIR)/gen-rpm-jh.spec
+	@#
+	@# rename the generated .rpm file to the name we want 
+	@#
+	@# -$(MV) $(OUTPUTDIR)/$(NATIVE_ARCH)/$(TEMP_JRE_RPMFILE_NAME) \
+	@#		$(OUTPUTDIR)/$(NATIVE_ARCH)/$(JRE_SHORT_BUNDLE_NAME).rpm
+	@#
+
+zip-RPM:
+	@# not being zipped right now.
+	@#
+	@# zip it up for inclusion in self-extracting zip...
+	@#
+	$(RM) $(OUTPUTDIR)/$(NATIVE_ARCH)/temp.rpm $(TEMP_DIR)/temp.bin
+	$(CD) $(OUTPUTDIR)/$(NATIVE_ARCH) ; \
+		$(ZIPEXE) -qryn nothing temp.rpm $(JRE_SHORT_BUNDLE_NAME).rpm
+	@# 
+	@# combine the self-extractor and .rpm.zip into a single binary...
+	@#
+	$(CAT) $(UNZIPSFX) $(OUTPUTDIR)/$(NATIVE_ARCH)/temp.rpm > $(TEMP_DIR)/temp.bin
+	$(SFX2SH) $(TEMP_DIR)/temp.bin \
+	          $(JRE_IMAGE_DIR)/LICENSE \
+		  $(OUTPUTDIR)/$(NATIVE_ARCH)/$(JRE_SHORT_BUNDLE_NAME)-rpm.sh \
+		  $(JRE_NODOTVERSION) \
+		  $(OUTPUTDIR)/$(JRE_TEMPORARY_DIR) \
+		  "$(JRE_PACKED_JARS)" \
+		  $(PLATFORM) \
+		  " " \
+		  "RPM"
+	$(MV) $(OUTPUTDIR)/$(NATIVE_ARCH)/$(JRE_SHORT_BUNDLE_NAME).rpm $(BIN_BUNDLEDIR)/$(JRE_BUNDLE_NAME).rpm
+	$(MV) $(OUTPUTDIR)/$(NATIVE_ARCH)/$(JRE_SHORT_BUNDLE_NAME)-rpm.sh $(BIN_BUNDLEDIR)/$(JRE_BUNDLE_NAME)-rpm.sh
+	@# 
+	@# remove the intermediate files...
+	@#
+	$(RM) $(TEMP_DIR)/temp.bin
+	$(RM) -r $(OUTPUTDIR)/$(NATIVE_ARCH)
+	$(RM) -r $(OUTPUTDIR)/$(JRE_TEMPORARY_DIR)
+	$(RM) $(OUTPUTDIR)/$(JRE_BUNDLE_NAME).bin $(OUTPUTDIR)/$(JRE_BUNDLE_NAME).zip
+
+jh-rpm-clobber:
+	$(RM) $(TEMP_DIR)/gen-rpm-jh.spec $(RPM_MACROFILE) 
+	$(RM) -r $(TEMP_DIR)/BUILD $(TEMP_DIR)/RPMS
+	$(RM) $(OUTPUTDIR)/$(JRE_RPM_TARFILE) 
+	$(RM) $(OUTPUTDIR)/$(ARCH)/$(JRE_SHORT_BUNDLE_NAME).rpm
+	$(RM) $(OUTPUTDIR)/$(ARCH)/temp.rpm $(TEMP_DIR)/temp.bin
+	$(RM) $(OUTPUTDIR)/$(ARCH)/$(JRE_SHORT_BUNDLE_NAME)-rpm.sh
+	$(RM) $(BIN_BUNDLEDIR)/$(JRE_BUNDLE_NAME).rpm
+	$(RM) $(BIN_BUNDLEDIR)/$(JRE_BUNDLE_NAME)-rpm.sh
+	$(RM) -r $(OUTPUTDIR)/$(ARCH)
+
diff --git a/jhMaster/JavaHelp/solarispkgs/GNUmakefile b/jhMaster/JavaHelp/solarispkgs/GNUmakefile
new file mode 100644
index 0000000000000000000000000000000000000000..e01ce34d8a7e4b12f5447ff9918832cd743dfd68
--- /dev/null
+++ b/jhMaster/JavaHelp/solarispkgs/GNUmakefile
@@ -0,0 +1,50 @@
+#
+# @(#)GNUmakefile	1.2 06/10/30
+# 
+# Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+# 
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.  Sun designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Sun in the LICENSE file that accompanied this code.
+# 
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+# 
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+# 
+# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+# CA 95054 USA or visit www.sun.com if you need additional information or
+# have any questions.
+#
+
+#
+# @(#)GNUmakefile 1.2 10/30/06
+#
+
+SUBDIRS = SUNWjhrt SUNWjhdev SUNWjhdem SUNWjhdoc
+
+all:
+	@for dir in $(SUBDIRS) ; do \
+	   echo "" ; \
+	   cd $$dir ; \
+	   $(MAKE) $@ ; \
+	   cd .. ; \
+	done
+
+clean: clobber
+
+clobber:
+	@for dir in $(SUBDIRS) ; do \
+	   echo "" ; \
+	   cd $$dir ; \
+	   $(MAKE) $@ ; \
+	   cd .. ; \
+	done
diff --git a/jhMaster/JavaHelp/solarispkgs/SUNWjhdem/GNUmakefile b/jhMaster/JavaHelp/solarispkgs/SUNWjhdem/GNUmakefile
new file mode 100644
index 0000000000000000000000000000000000000000..d4ec250bae26d5615f1fca96a556f94aa8a6c680
--- /dev/null
+++ b/jhMaster/JavaHelp/solarispkgs/SUNWjhdem/GNUmakefile
@@ -0,0 +1,219 @@
+#
+# @(#)GNUmakefile	1.11 06/10/30
+# 
+# Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+# 
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.  Sun designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Sun in the LICENSE file that accompanied this code.
+# 
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+# 
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+# 
+# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+# CA 95054 USA or visit www.sun.com if you need additional information or
+# have any questions.
+#
+
+# Install for JavaHelp.
+# This is a Solaris GNUmakefile
+
+PKGNAME=SUNWjhdem
+J2SE=jdk
+#OPT=j2se/opt
+OPT=$(J2SE)/packages
+#DJH=j2se/opt/javahelp
+DJH=$(OPT)/javax.help-2.0
+INSTALL=$(PKGNAME)/install
+RELOC=$(PKGNAME)/reloc
+PWD=$(shell pwd)
+OWNERGROUP=$(shell id | cut -f2  -d'(' | cut -f1 -d')') $(shell groups | cut -f1 -d' ')
+PKGPATH=$(PWD)/$(PKGNAME)
+
+Dbin=$(DJH)/bin
+
+Ddemos=$(DJH)/demos $(DJH)/demos/bin $(DJH)/demos/hsjar \
+       $(DJH)/demos/lib $(DJH)/demos/hs \
+       $(DJH)/demos/hs/merge $(DJH)/demos/hs/newmerge\
+       $(DJH)/demos/browser
+
+Ddemosrc=$(DJH)/demos/src/sunw/demo/jhdemo \
+	 $(DJH)/demos/src/sunw/demo/idedemo \
+         $(DJH)/demos/src/sunw/demo/classviewer \
+         $(DJH)/demos/src/sunw/demo/classviewer/plaf/basic \
+         $(DJH)/demos/src/sunw/demo/classviewer/plaf/metal \
+         $(DJH)/demos/src/sunw/demo/classviewer/plaf/motif \
+         $(DJH)/demos/src/sunw/demo/classviewer/plaf/windows \
+         $(DJH)/demos/src/sunw/demo/searchdemo \
+         $(DJH)/demos/src/sunw/demo/merge \
+         $(DJH)/demos/src/sunw/demo/newmerge \
+         $(DJH)/demos/src/sunw/demo/browser
+
+TOP=../..
+DD=$(TOP)/demos
+JD=$(TOP)/javahelp
+PKGTOP=..
+
+CP=/bin/cp -p -f
+RM=/bin/rm -f
+TAR=/usr/sbin/tar
+MV=/bin/mv -f
+JAR=jar
+
+CPDIR=/bin/cp -pr -f
+
+all: dirs helpset demo demosrc package
+	pkgmk -o -d $(PWD) -r $(PWD) -f $(PWD)/prototype basedir=$(PWD)
+
+dirs: $(J2SE) $(OPT) $(DJH)
+
+package: $(PKGPATH) pkginfo proto
+
+pkginfo:
+	sed s/\<REV\>/\,REV\=`date +%Y.%m.%d`/ < pkginfo.base > pkginfo
+
+proto:
+	chmod -R g-s $(J2SE)
+	chmod -R o+r $(J2SE)
+	pkgproto $(J2SE) > prototype.tmp
+	sed s/"$(OWNERGROUP)"/"root bin"/ prototype.tmp > prototype.build
+	$(RM) prototype.tmp
+	if [ -f prototype.base ]; then \
+		cat prototype.base prototype.build > prototype; \
+		$(RM) prototype.build; \
+	else \
+		$(MV) prototype.build prototype; \
+	fi; \
+
+
+#
+# HelpSets
+#
+
+helpset: $(Ddemos)
+	$(CP) $(DD)/hsjar/holidays.jar $(DJH)/demos/hsjar/holidays.jar
+	chmod 644 $(DJH)/demos/hsjar/holidays.jar
+	$(CP) $(DD)/hsjar/animals.jar $(DJH)/demos/hsjar/animals.jar
+	chmod 644 $(DJH)/demos/hsjar/animals.jar
+	$(CP) $(DD)/hsjar/invertebrates.jar $(DJH)/demos/hsjar/invertebrates.jar
+	chmod 644 $(DJH)/demos/hsjar/invertebrates.jar
+	$(CP) $(DD)/hsjar/vertebrates.jar $(DJH)/demos/hsjar/vertebrates.jar
+	chmod 644 $(DJH)/demos/hsjar/vertebrates.jar
+	$(CP) $(DD)/hsjar/apidoc.jar $(DJH)/demos/hsjar/apidoc.jar
+	chmod 644 $(DJH)/demos/hsjar/apidoc.jar
+	$(CP) $(DD)/hsjar/idehelp.jar $(DJH)/demos/hsjar/idehelp.jar
+	chmod 644 $(DJH)/demos/hsjar/idehelp.jar
+	$(CP) $(DD)/hsjar/object.jar $(DJH)/demos/hsjar/object.jar
+	chmod 644 $(DJH)/demos/hsjar/object.jar
+	$(CP) $(DD)/hsjar/idehelp_de.jar $(DJH)/demos/hsjar/idehelp_de.jar
+	chmod 644 $(DJH)/demos/hsjar/idehelp_de.jar
+	$(CP) $(DD)/hsjar/idehelp_en.jar $(DJH)/demos/hsjar/idehelp_en.jar
+	chmod 644 $(DJH)/demos/hsjar/idehelp_en.jar
+	$(CP) $(DD)/hsjar/idehelp_ja.jar $(DJH)/demos/hsjar/idehelp_ja.jar
+	chmod 644 $(DJH)/demos/hsjar/idehelp_ja.jar
+	mkdir -m 755 -p $(DJH)/demos/hs ; \
+	( cd $(DD)/hs ; echo merge/GNUmakefile > exclude.tmp ) ; \
+	( cd $(DD)/hs ; $(TAR) cFFXf exclude.tmp - merge ) | (cd $(DJH)/demos/hs ; $(TAR) xf - ) ; \
+	chmod -R u+w $(DJH)/demos/hs/merge
+	rm $(DD)/hs/exclude.tmp
+	( cd $(DD)/hs ; echo newmerge/GNUmakefile > exclude.tmp ) ; \
+	( cd $(DD)/hs ; $(TAR) cFFXf exclude.tmp - newmerge ) | (cd $(DJH)/demos/hs ; $(TAR) xf - ) ; \
+	chmod -R u+w $(DJH)/demos/hs/newmerge
+	rm $(DD)/hs/exclude.tmp
+	chmod -R g-w $(DJH)/demos/hs
+
+#
+# Demos
+#
+
+demo: $(Ddemos)
+	$(CP) $(DD)/idedemo/idedemo.jar $(DJH)/demos/bin/idedemo.jar
+	chmod 644 $(DJH)/demos/bin/idedemo.jar
+
+	$(CP) $(DD)/merge/merge.jar $(DJH)/demos/bin/merge.jar
+	chmod 644 $(DJH)/demos/bin/merge.jar
+
+	$(CP) $(DD)/newmerge/newmerge.jar $(DJH)/demos/bin/newmerge.jar
+	chmod 644 $(DJH)/demos/bin/newmerge.jar
+
+	$(CP) $(DD)/bin/apiviewer.jar $(DJH)/demos/bin/apiviewer.jar
+	chmod 644 $(DJH)/demos/bin/apiviewer.jar
+
+	$(CP) $(DD)/bin/object.jar $(DJH)/demos/bin/object.jar
+	chmod 644 $(DJH)/demos/bin/object.jar
+
+	$(CP) $(DD)/bin/hsviewer.jar $(DJH)/demos/bin/hsviewer.jar
+	chmod 644 $(DJH)/demos/bin/hsviewer.jar
+
+	$(CP) $(DD)/bin/UserGuide.jar $(DJH)/demos/bin/UserGuide.jar
+	chmod 644 $(DJH)/demos/bin/hsviewer.jar
+
+	$(CP) $(DD)/lib/classviewer.jar $(DJH)/demos/lib/classviewer.jar
+	chmod 644 $(DJH)/demos/lib/classviewer.jar
+	$(CP) $(DD)/lib/searchdemo.jar $(DJH)/demos/lib/searchdemo.jar
+	chmod 644 $(DJH)/demos/lib/searchdemo.jar
+	$(CP) $(DD)/lib/browserdemo.jar $(DJH)/demos/browser/browserdemo.jar
+	chmod 644 $(DJH)/demos/browser/browserdemo.jar
+	$(CP) $(DD)/newbrowser/*.html $(DJH)/demos/browser/
+	$(CP) $(DD)/newbrowser/demo_instructions $(DJH)/demos/browser/
+	chmod -R u+w $(DJH)/demos/browser
+
+#
+# Demo sources
+#
+
+demosrc: $(Ddemosrc) 
+	$(CP) $(DD)/jhdemo/sunw/demo/jhdemo/JHLauncher.java $(DJH)/demos/src/sunw/demo/jhdemo/
+	$(CP) $(DD)/jhdemo/sunw/demo/jhdemo/Runner.java $(DJH)/demos/src/sunw/demo/jhdemo/
+	$(CP) $(DD)/jhdemo/sunw/demo/jhdemo/ElementTreePanel.java $(DJH)/demos/src/sunw/demo/jhdemo/
+	$(CP) $(DD)/README.install $(DJH)/demos/README
+	chmod 644 $(DJH)/demos/README
+	$(CP) $(DD)/idedemo/sunw/demo/idedemo/ApiDemo.java $(DJH)/demos/src/sunw/demo/idedemo/
+	$(CP) $(DD)/idedemo/sunw/demo/idedemo/IdeDemo.properties $(DJH)/demos/src/sunw/demo/idedemo/
+	here=`pwd` ; \
+	  cd  $(DJH)/demos/src/sunw/demo/idedemo ; \
+	  $(JAR) -xf $$here/$(DD)/idedemo/images.jar
+	$(CP) $(DD)/searchdemo/sunw/demo/searchdemo/ClientSearchEngine.java $(DJH)/demos/src/sunw/demo/searchdemo/
+	$(CP) $(DD)/searchdemo/sunw/demo/searchdemo/ClientSearchQuery.java $(DJH)/demos/src/sunw/demo/searchdemo/
+	$(CP) $(DD)/apidoc/sunw/demo/classviewer/ClassViewerView.java $(DJH)/demos/src/sunw/demo/classviewer/
+	$(CP) $(DD)/apidoc/sunw/demo/classviewer/ClassViewerNavigator.java $(DJH)/demos/src/sunw/demo/classviewer/
+	$(CP) $(DD)/apidoc/sunw/demo/classviewer/plaf/basic/BasicClassViewerNavigatorUI.java $(DJH)/demos/src/sunw/demo/classviewer/plaf/basic/
+	$(CP) $(DD)/apidoc/sunw/demo/classviewer/plaf/metal/MetalClassViewerNavigatorUI.java $(DJH)/demos/src/sunw/demo/classviewer/plaf/metal/
+	$(CP) $(DD)/apidoc/sunw/demo/classviewer/plaf/motif/MotifClassViewerNavigatorUI.java $(DJH)/demos/src/sunw/demo/classviewer/plaf/motif/
+	$(CP) $(DD)/apidoc/sunw/demo/classviewer/plaf/windows/WindowsClassViewerNavigatorUI.java $(DJH)/demos/src/sunw/demo/classviewer/plaf/windows/
+	$(CP) $(DD)/merge/sunw/demo/merge/Merge.java $(DJH)/demos/src/sunw/demo/merge/
+	$(CP) $(DD)/newmerge/sunw/demo/newmerge/Merge.java $(DJH)/demos/src/sunw/demo/newmerge/
+	$(CP) $(DD)/newmerge/sunw/demo/newmerge/HSFilter.java $(DJH)/demos/src/sunw/demo/newmerge/
+	$(CP) $(DD)/newmerge/sunw/demo/newmerge/JarAccessory.java $(DJH)/demos/src/sunw/demo/newmerge/
+	$(CP) $(DD)/newbrowser/sunw/demo/browser/HelpButton.java $(DJH)/demos/src/sunw/demo/browser/
+	chmod -R u+w $(DJH)/demos/src
+	chmod -R g-w $(DJH)/demos/src
+
+#
+# Directory creation
+#
+$(J2SE) $(OPT) $(DJH) $(Ddemos) $(Ddemosrc) $(Dbin) $(PKGPATH):
+	mkdir -m 755 -p $@
+	chmod 755 $@
+
+#
+# Cleanup
+#
+clean: clobber
+
+clobber:
+	$(RM) -rf $(J2SE)
+	$(RM) -rf $(PKGNAME)
+	$(RM) -rf prototype
+	$(RM) -rf pkginfo
+
diff --git a/jhMaster/JavaHelp/solarispkgs/SUNWjhdev/GNUmakefile b/jhMaster/JavaHelp/solarispkgs/SUNWjhdev/GNUmakefile
new file mode 100644
index 0000000000000000000000000000000000000000..e88d80fdc0b837088e00d6e18927184cec13cfec
--- /dev/null
+++ b/jhMaster/JavaHelp/solarispkgs/SUNWjhdev/GNUmakefile
@@ -0,0 +1,148 @@
+#
+# @(#)GNUmakefile	1.9 06/10/30
+# 
+# Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+# 
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.  Sun designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Sun in the LICENSE file that accompanied this code.
+# 
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+# 
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+# 
+# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+# CA 95054 USA or visit www.sun.com if you need additional information or
+# have any questions.
+#
+
+# Install for JavaHelp.
+# This is a Solaris GNUmakefile
+
+PKGNAME=SUNWjhdev
+J2SE=jdk
+#OPT=j2se/opt
+OPT=$(J2SE)/packages
+#DJH=j2se/opt/javahelp
+DJH=$(OPT)/javax.help-2.0
+INSTALL=$(PKGNAME)/install
+RELOC=$(PKGNAME)/reloc
+PWD=$(shell pwd)
+OWNERGROUP=$(shell id | cut -f2  -d'(' | cut -f1 -d')') $(shell groups | cut -f1 -d' ')
+PKGPATH=$(PWD)/$(PKGNAME)
+
+Dlib=$(DJH)/lib
+Ddtd=$(Dlib)/dtd
+Dbin=$(DJH)/bin
+
+DTDS=\
+	$(Ddtd)/helpset_1_0.dtd \
+	$(Ddtd)/map_1_0.dtd \
+	$(Ddtd)/toc_1_0.dtd \
+	$(Ddtd)/index_1_0.dtd
+
+Dimplsrc=com/sun/java/help/impl/JHSecondaryViewer.java \
+	 com/sun/java/help/impl/JHSecondaryViewerBeanInfo.java \
+	 com/sun/java/help/impl/ViewAwareComponent.java
+
+DSRC=$(DJH)/src
+
+JD=../../javahelp
+TOP=../..
+DOCD=$(TOP)/doc
+SRCD=$(TOP)/src
+PKGTOP=..
+
+CP=/bin/cp -p -f
+RM=/bin/rm -f
+TAR=/usr/sbin/tar
+MV=/bin/mv -f
+JAR=jar
+
+CPDIR=/bin/cp -pr -f
+
+all: dirs libs bins source package
+	pkgmk -o -d $(PWD) -r $(PWD) -f $(PWD)/prototype basedir=$(PWD)
+
+dirs: $(J2SE) $(OPT) $(DJH)
+
+package: $(PKGPATH) pkginfo proto
+
+pkginfo:
+	sed s/\<REV\>/\,REV\=`date +%Y.%m.%d`/ < pkginfo.base > pkginfo
+
+proto:
+	chmod -R g-s $(J2SE)
+	pkgproto $(J2SE) > prototype.tmp
+	sed s/"$(OWNERGROUP)"/"root bin"/ prototype.tmp > prototype.build
+	$(RM) prototype.tmp
+	if [ -f prototype.base ]; then \
+		cat prototype.base prototype.build > prototype; \
+		$(RM) prototype.build; \
+	else \
+		$(MV) prototype.build prototype; \
+	fi; \
+
+
+#
+# the JavaHelp libraries
+#
+
+libs: $(Ddtd) $(DTDS)
+
+$(Ddtd)/%.dtd: $(DOCD)/public-spec/dtd/%.dtd
+	$(CP) $< $@
+	chmod 644 $@
+
+#
+# predefined commands
+#
+
+bins: $(Dbin)
+	$(CP) $(JD)/bin/jhindexer_solsparc $(Dbin)/jhindexer
+	chmod 755 $(Dbin)/jhindexer
+	$(CP) $(JD)/bin/jhsearch_solsparc $(Dbin)/jhsearch
+	chmod 755 $(Dbin)/jhsearch
+
+#
+# source
+#
+source:
+	mkdir -p $(DSRC)
+	$(RM) -rf $(DSRC)/*
+	cd $(SRCD)/new ; \
+	$(TAR) cFFf - . | (cd $(PWD)/$(DSRC) ; $(TAR) xf - )
+	cd $(SRCD)/impl; \
+	$(TAR) cf - $(Dimplsrc) | (cd $(PWD)/$(DSRC) ; $(TAR) xf - )
+	cd $(PWD)/$(DSRC); jar -cMvf $(PWD)/$(DJH)/src.jar .
+	chmod g-w $(DJH)/src.jar
+	$(RM) -rf $(DSRC);
+	chmod 755 $(Dlib);
+
+#
+# Directory creation
+#
+$(J2SE) $(OPT) $(DJH) $(Dlib) $(Ddtd) $(Dbin) $(PKGPATH):
+	mkdir -m 755 -p $@
+	chmod 755 $@
+
+#
+# Cleanup
+#
+clean: clobber
+
+clobber:
+	$(RM) -rf $(J2SE)
+	$(RM) -rf $(PKGNAME)
+	$(RM) -rf prototype
+	$(RM) -rf pkginfo
+
diff --git a/jhMaster/JavaHelp/solarispkgs/SUNWjhdoc/GNUmakefile b/jhMaster/JavaHelp/solarispkgs/SUNWjhdoc/GNUmakefile
new file mode 100644
index 0000000000000000000000000000000000000000..a2444e83cc7a23ff340f2f51ca7edb32d5265de2
--- /dev/null
+++ b/jhMaster/JavaHelp/solarispkgs/SUNWjhdoc/GNUmakefile
@@ -0,0 +1,141 @@
+#
+# @(#)GNUmakefile	1.7 06/10/30
+# 
+# Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+# 
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.  Sun designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Sun in the LICENSE file that accompanied this code.
+# 
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+# 
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+# 
+# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+# CA 95054 USA or visit www.sun.com if you need additional information or
+# have any questions.
+#
+
+# Install for JavaHelp.
+# This is a Solaris GNUmakefile
+
+PKGNAME=SUNWjhdoc
+J2SE=jdk
+#OPT=j2se/opt
+OPT=$(J2SE)/packages
+#DJH=j2se/opt/javahelp
+DJH=$(OPT)/javax.help-2.0
+INSTALL=$(PKGNAME)/install
+RELOC=$(PKGNAME)/reloc
+PWD=$(shell pwd)
+OWNERGROUP=$(shell id | cut -f2  -d'(' | cut -f1 -d')') $(shell groups | cut -f1 -d' ')
+PKGPATH=$(PWD)/$(PKGNAME)
+
+DDOC=$(DJH)/doc
+
+Ddocs=$(DDOC)/jhug $(DDOC)/jhug/overview $(DDOC)/jhug/author \
+      $(DDOC)/jhug/images $(DDOC)/jhug/images/overview $(DDOC)/jhug/dev \
+      $(DDOC)/jhug/merge $(DDOC)/jhug/locale $(DDOC)/jhug/release \
+      $(DDOC)/jhug/JavaHelpSearch $(DDOC)/api $(DDOC)/css
+
+Ddocimages=$(DDOC)/images
+
+Dspecs=$(DDOC)/spec
+
+TOP=../..
+JD=$(TOP)/javahelp
+DOCD=$(TOP)/doc
+PKGTOP=..
+
+ifeq ($(JHUGDIR),)
+JHUGDIR=$(TOP)/doc/jhug
+endif
+JHUG=jhug.pdf
+
+CP=/bin/cp -p -f
+RM=/bin/rm -f
+TAR=/usr/sbin/tar
+MV=/bin/mv -f
+JAR=jar
+
+CPDIR=/bin/cp -pr -f
+
+all: dirs spec docs package
+	pkgmk -o -d $(PWD) -r $(PWD) -f $(PWD)/prototype basedir=$(PWD)
+
+dirs: $(J2SE) $(OPT) $(DJH) $(DDOC)
+
+package: $(PKGPATH) pkginfo proto
+
+pkginfo:
+	sed s/\<REV\>/\,REV\=`date +%Y.%m.%d`/ < pkginfo.base > pkginfo
+
+proto:
+	chmod -R g-s $(J2SE)
+	pkgproto $(J2SE) > prototype.tmp
+	sed s/"$(OWNERGROUP)"/"root bin"/ prototype.tmp > prototype.build
+	$(RM) prototype.tmp
+	if [ -f prototype.base ]; then \
+		cat prototype.base prototype.build > prototype; \
+		$(RM) prototype.build; \
+	else \
+		$(MV) prototype.build prototype; \
+	fi; \
+
+
+#
+# JavaHelp Specification 
+#
+spec: $(Dspecs) 
+	mkdir -m 755 -p $(DDOC)/spec
+	cp $(DOCD)/public-spec/V2.0/JavaHelp_V2_0_Specification.pdf $(DDOC)/spec
+	chmod -R u+w $(DDOC)/spec	
+
+#
+# Generic Documentation
+#
+docs: $(Ddocs) docimages $(JHUGDIR)/$(JHUG)
+	cd $(DOCD) ; \
+	$(TAR) cFFf - jhug | (cd $(PWD)/$(DDOC) ; $(TAR) xf - )
+	$(MV) $(DDOC)/jhug/$(JHUG) $(DDOC)/$(JHUG)
+	chmod u+w $(DDOC)/$(JHUG) 
+	chmod -R u+w $(DDOC)/jhug
+	chmod g-w $(DDOC)/jhug/JavaHelpSearch/*
+	$(RM) $(DDOC)/jhug/GNUmakefile $(DDOC)/jhug/createps.sh
+	$(CPDIR) $(DOCD)/api/* $(DDOC)/api/
+	chmod -R g-w $(DDOC)/api
+	$(CP) $(DOCD)/css/default.css $(DDOC)/css/default.css
+	chmod u+w $(DDOC)/css/default.css
+
+docimages: $(Ddocimages)
+	cd $(DOCD) ; \
+	$(TAR) cFFf - images | (cd $(PWD)/$(DDOC) ; $(TAR) xf - )
+	chmod -R u+w $(DDOC)/images
+
+#
+# Directory creation
+#
+$(J2SE) $(OPT) $(DJH) $(DDOC) $(Ddocs) $(Ddocimages) $(Dspecs) $(PKGPATH):
+	mkdir -m 755 -p $@
+	chmod 755 $@
+
+#
+# Cleanup
+#
+clean: clobber
+
+clobber:
+	$(RM) -rf $(J2SE)
+	$(RM) -rf $(PKGNAME)
+	$(RM) -rf prototype
+	$(RM) -rf pkginfo
+
diff --git a/jhMaster/JavaHelp/solarispkgs/SUNWjhrt/GNUmakefile b/jhMaster/JavaHelp/solarispkgs/SUNWjhrt/GNUmakefile
new file mode 100644
index 0000000000000000000000000000000000000000..40afaccc750909eb7c70a765e4c51682146c14a7
--- /dev/null
+++ b/jhMaster/JavaHelp/solarispkgs/SUNWjhrt/GNUmakefile
@@ -0,0 +1,119 @@
+#
+# @(#)GNUmakefile	1.8 06/10/30
+# 
+# Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+# 
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.  Sun designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Sun in the LICENSE file that accompanied this code.
+# 
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+# 
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+# 
+# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+# CA 95054 USA or visit www.sun.com if you need additional information or
+# have any questions.
+#
+
+# Install for JavaHelp.
+# This is a Solaris GNUmakefile
+
+PKGNAME=SUNWjhrt
+J2SE=jdk
+#OPT=j2se/opt
+OPT=$(J2SE)/packages
+#DJH=j2se/opt/javahelp
+DJH=$(OPT)/javax.help-2.0
+INSTALL=$(PKGNAME)/install
+RELOC=$(PKGNAME)/reloc
+PWD=$(shell pwd)
+OWNERGROUP=$(shell id | cut -f2  -d'(' | cut -f1 -d')') $(shell groups | cut -f1 -d' ')
+PKGPATH=$(PWD)/$(PKGNAME)
+
+Dlib=$(DJH)/lib
+
+LIBS=$(Dlib)/jhall.jar
+
+JD=../../javahelp
+TOP=../..
+PKGTOP=..
+
+CP=/bin/cp -p -f
+RM=/bin/rm -f
+TAR=/usr/sbin/tar
+MV=/bin/mv -f
+JAR=jar
+
+CPDIR=/bin/cp -pr -f
+
+all: dirs misc libs package
+	echo owner group is $(OWNERGROUP)
+	pkgmk -f $(PWD)/prototype -d $(PWD) -o -r $(PWD) basedir=$(PWD)
+
+dirs: $(J2SE) $(OPT) $(DJH)
+
+package: $(PKGPATH) pkginfo proto
+
+pkginfo:
+	sed s/\<REV\>/\,REV\=`date +%Y.%m.%d`/ < pkginfo.base > pkginfo
+
+proto:  
+	chmod -R g-s $(J2SE)
+	pkgproto $(J2SE) > prototype.tmp
+	sed s/"$(OWNERGROUP)"/"root bin"/ prototype.tmp > prototype.build
+	$(RM) prototype.tmp
+	if [ -f prototype.base ]; then \
+		cat prototype.base prototype.build > prototype; \
+		$(RM) prototype.build; \
+	else \
+		$(MV) prototype.build prototype; \
+	fi; \
+
+
+#
+# Miscellaneous information
+#
+misc: $(DJH)
+	$(CP) $(TOP)/LICENSE.html $(DJH)/LICENSE.html
+	chmod 644 $(DJH)/LICENSE.html
+
+
+#
+# the JavaHelp libraries
+#
+
+libs: jars 
+
+jars: $(Dlib) $(LIBS)
+
+$(Dlib)/%.jar: $(JD)/lib/%.jar
+	$(CP) $< $@
+	chmod 644 $@
+
+#
+# Directory creation
+#
+$(J2SE) $(OPT) $(DJH) $(Dlib) $(PKGPATH):
+	mkdir -m 755 -p $@
+	chmod 755 $@
+#
+# Cleanup
+#
+clean: clobber
+
+clobber:
+	$(RM) -rf $(J2SE)
+	$(RM) -rf $(PKGNAME)
+	$(RM) -rf prototype
+	$(RM) -rf pkginfo
+
diff --git a/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/CustomKit.java b/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/CustomKit.java
new file mode 100644
index 0000000000000000000000000000000000000000..fa10f0ff8fddf854faeb27dbaa6c1123a2a443d2
--- /dev/null
+++ b/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/CustomKit.java
@@ -0,0 +1,387 @@
+/*
+ * @(#)CustomKit.java	1.15 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.java.help.impl;
+
+import java.util.Enumeration;
+import java.util.Vector;
+import java.awt.*;
+import java.net.*;
+import java.io.*;
+import javax.swing.*;
+import javax.swing.text.*;
+import java.beans.*;
+import java.lang.reflect.*;
+import javax.swing.text.html.*;
+import java.awt.event.MouseMotionListener;
+import java.awt.event.MouseEvent;
+
+/**
+ * Subclass of HTMLEditorKit from Swing to adds better functionality
+ * for handing <OBJECT> tags and supports some special classes
+ * for JavaHelp.
+ *
+ * @author Tim Prinzing
+ * @author Eduardo Pelegri-Llopart
+ * @version	1.15	10/30/06
+ */
+
+public class CustomKit extends HTMLEditorKit {
+
+    public CustomKit() {
+	super();
+    }
+
+    /**
+     * Clone the editorkit
+     */
+    public Object clone() {
+	return new CustomKit();
+    }
+
+    /**
+     * Called when the kit is being installed into the
+     * a JEditorPane. 
+     *
+     * @param c the JEditorPane
+     */
+      public void install(JEditorPane c) {
+	c.addMouseMotionListener(mouseHandler);
+	super.install(c);
+    }
+
+    /**
+     * Called when the kit is being removed from the
+     * JEditorPane.  This is used to unregister any 
+     * listeners that were attached.
+     *
+     * @param c the JEditorPane
+     */
+    public void deinstall(JEditorPane c) {
+	c.removeMouseMotionListener(mouseHandler);
+	super.deinstall(c);
+    }
+
+    public Document createDefaultDocument() {
+	// normally we would do exactly what HTMLEditor.createDefaultDocument
+	// does:
+	//
+	// StyleSheet styles = getStyleSheet();
+	// StyleSheet ss = new StyleSheet();
+	// ss.addStyleSheet(styles);
+	// HTMLDocument doc = new HTMLDocument(ss);
+	//
+	// However, since StyleSheet.addStyleSheet is package private, we'll
+	// have to work around the problem.
+	HTMLDocument tmpDoc = (HTMLDocument)super.createDefaultDocument();
+
+	HTMLDocument doc = new CustomDocument(tmpDoc.getStyleSheet());
+	doc.putProperty ("__PARSER__", getParser());
+	doc.setAsynchronousLoadPriority(4);
+	doc.setTokenThreshold(100);
+	debug("fetch custom document");
+	return doc;
+    }
+
+    /**
+     * Fetch a factory that is suitable for producing 
+     * views of any models that are produced by this
+     * kit.  
+     *
+     * @return the factory
+     */
+    public ViewFactory getViewFactory() {
+	debug("fetched custom factory");
+	return new CustomFactory();
+    }
+
+    // --- variables ------------------------------------------
+    private MouseMotionListener mouseHandler = new MouseHandler();
+
+    /**
+     * Class to watch the associated component and change the
+     * cursor when in a hyperlink
+     */
+    public static class MouseHandler implements MouseMotionListener {
+
+	private Element curElem = null;
+	private Cursor origCursor;
+	private Cursor handCursor=null;
+
+	// ignore the drags
+	public void mouseDragged(MouseEvent e) {
+	}
+
+	// track the moving of the mouse.
+	public void mouseMoved(MouseEvent e) {
+	    JEditorPane editor = (JEditorPane) e.getSource();
+
+	    if (!editor.isEditable()) {
+		Point pt = new Point(e.getX(), e.getY());
+		int pos = editor.viewToModel(pt);
+		if (pos >= 0) {
+		    Document doc = editor.getDocument();
+		    if (doc instanceof HTMLDocument) {
+			HTMLDocument hdoc = (HTMLDocument) doc;
+			Element elem = hdoc.getCharacterElement(pos);
+			AttributeSet a = elem.getAttributes();
+			AttributeSet anchor = (AttributeSet) a.getAttribute(HTML.Tag.A);
+			String href = (anchor != null) ? 
+			    (String) anchor.getAttribute(HTML.Attribute.HREF) 
+			    : null;
+			
+			if (href != null) {
+			    if (curElem != elem) {
+				curElem = elem;
+				if (origCursor == null) {
+				    origCursor = editor.getCursor();
+				}
+				if (handCursor == null) {
+				    handCursor = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR);
+				}
+				editor.setCursor(handCursor);
+			    }
+			} else {
+			    if (curElem != null) {
+				curElem = null;
+				editor.setCursor(origCursor);
+			    }
+			}
+		    }
+		}
+	    }
+	}
+    }
+
+    static class CustomFactory extends HTMLFactory {
+
+        public View create(Element elem) {
+	    Object o = elem.getAttributes().getAttribute(StyleConstants.NameAttribute);
+	    if (o instanceof HTML.Tag) {
+		HTML.Tag kind = (HTML.Tag) o;
+		if (kind == HTML.Tag.OBJECT) {
+		    debug("creating ObjectView1 for: " + elem);
+		    return new ObjectView1(elem);
+		}
+	    }
+	    return super.create(elem);
+	}
+
+    }
+
+    static class CustomDocument extends HTMLDocument {
+
+	CustomDocument(StyleSheet s) {
+	    super(s);
+	}
+
+        public HTMLEditorKit.ParserCallback getReader(int pos) {
+	    Object desc = getProperty(Document.StreamDescriptionProperty);
+	    if (desc instanceof URL) { 
+		setBase((URL)desc);
+	    }
+	    HTMLReader reader = new CustomReader(pos);
+	    return reader;
+	}
+
+	class CustomReader extends HTMLReader {
+
+	    public CustomReader(int offset) {
+		super(offset);
+		registerTag(HTML.Tag.PARAM, new ObjectAction1());
+	    }
+
+	    Vector getParseBuffer() {
+		return parseBuffer;
+	    }
+
+	    class ObjectAction1 extends SpecialAction {
+		
+                public void start(HTML.Tag t, MutableAttributeSet a) {
+		    if (t == HTML.Tag.PARAM) {
+			addParameter(a);
+		    } else {
+			super.start(t, a);
+		    }
+		}
+		
+  	        public void end(HTML.Tag t) {
+		    if (t != HTML.Tag.PARAM) {
+			super.end(t);
+		    }
+		}
+		
+		void addParameter(AttributeSet a) {
+		    debug ("addParameter AttributeSet=" + a);
+		    String name = (String) a.getAttribute(HTML.Attribute.NAME);
+		    String value = (String) a.getAttribute(HTML.Attribute.VALUE);
+		    if ((name != null) && (value != null)) {
+			ElementSpec objSpec = (ElementSpec) getParseBuffer().lastElement();
+			MutableAttributeSet objAttr = (MutableAttributeSet) objSpec.getAttributes();
+			objAttr.addAttribute(name, value);
+		    }
+		}
+	    }
+	}
+    }
+
+    static class ObjectView1 extends ComponentView  {
+
+	/**
+	 * Creates a new ObjectView object.
+	 *
+	 * @param elem the element to decorate
+	 */
+	public ObjectView1(Element elem) {
+	    super(elem);
+	}
+    
+	/**
+	 * Create the component.  The classid is used
+	 * as a specification of the classname, which
+	 * we try to load.
+	 */
+	protected Component createComponent() {
+	    AttributeSet attr = getElement().getAttributes();
+	    debug("attr: " + attr.copyAttributes());
+	    String classname = (String) attr.getAttribute(HTML.Attribute.CLASSID);
+	    try {
+		int colon = classname.indexOf(':');
+		if (colon != -1) {
+		    String classtype= classname.substring(0, colon).toLowerCase();
+		    if (classtype.compareTo("java") == 0) {
+			classname = classname.substring(colon + 1);
+			Class c = getClass(classname);
+			Object o = c.newInstance();
+			if (o instanceof Component) {
+			    Component comp = (Component) o;
+			    if (o instanceof ViewAwareComponent) {
+				((ViewAwareComponent) comp).setViewData(this);
+			    }
+			    setParameters(comp, attr);
+			    return comp;
+			}
+		    }
+		}
+	    } catch (Throwable e) {
+		// couldn't create a component... fall through to the 
+		// couldn't load representation.
+	    }
+	    
+	    return getUnloadableRepresentation();
+	}
+    
+	/**
+	 * Fetch a component that can be used to represent the
+	 * object if it can't be created.
+	 */
+	Component getUnloadableRepresentation() {
+	    // PENDING(prinz) get some artwork and return something
+	    // interesting here.
+	    Component comp = new JLabel("??");
+	    comp.setForeground(Color.red);
+	    return comp;
+	}
+    
+	/**
+	 * Get a Class object to use for loading the classid.
+	 *
+	 * If possible, the Classloader used to load the associated
+	 * Document is used. This would typically be the same as the ClassLoader
+	 * used to load the EditorKit.
+	 *
+	 * If the documents ClassLoader is null,
+	 * <code>Class.forName</code> is used.
+	 */
+	private Class getClass(String classname) throws ClassNotFoundException {
+	    Class klass = null;
+	    
+	    Class docClass = getDocument().getClass();
+	    ClassLoader loader = docClass.getClassLoader();
+	    if (loader != null) {
+		klass = loader.loadClass(classname);
+	    }
+	    if (klass == null) {
+		klass = Class.forName(classname);
+	    }
+	    return klass;
+	}
+    
+	/**
+	 * Initialize this component according the KEY/VALUEs passed in
+	 * via the &lt;param&gt; elements in the corresponding 
+	 * &lt;object&gt; element.
+	 */
+	private void setParameters(Component comp, AttributeSet attr) {
+	    Class k = comp.getClass();
+	    BeanInfo bi;
+	    try {
+		bi = Introspector.getBeanInfo(k);
+	    } catch (IntrospectionException ex) {
+		debug("introspector failed, ex: "+ex);
+		return;		// quit for now
+	    }
+	    PropertyDescriptor props[] = bi.getPropertyDescriptors();
+	    for (int i=0; i < props.length; i++) {
+		debug("checking on props[i]: "+props[i].getName());
+		Object v = attr.getAttribute(props[i].getName());
+		if (v instanceof String) {
+		    // found a property parameter
+		    String value = (String) v;
+		    Method writer = props[i].getWriteMethod();
+		    if (writer == null) {
+			// read-only property. ignore
+			return;	// for now
+		    }
+		    Class[] params = writer.getParameterTypes();
+		    if (params.length != 1) {
+			// zero or more than one argument, ignore
+			return;	// for now
+		    }
+		    String [] args = { value };
+		    try {
+			writer.invoke(comp, (java.lang.Object[]) args);
+			debug("Invocation succeeded");
+		    } catch (Exception ex) {
+			debug("Invocation failed");
+			// invocation code
+		    }
+		}
+	    }
+	}
+    }
+
+    /**
+     * For printf debugging.
+     */
+    private final static boolean debug = false;
+    private static void debug(String str) {
+        if (debug) {
+            System.out.println("CustomKit: " + str);
+        }
+    }
+}
diff --git a/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/DocPConst.java b/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/DocPConst.java
new file mode 100644
index 0000000000000000000000000000000000000000..4050a41563d22eced6f7f26f3eeeb40607cc6117
--- /dev/null
+++ b/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/DocPConst.java
@@ -0,0 +1,60 @@
+/*
+ * @(#)DocPConst.java	1.10 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @(#) DocPConst.java 1.10 - last change made 10/30/06
+ *
+ * This class defines constants used by the Document Parser in the 
+ * java.help
+ * package.
+ */
+
+package com.sun.java.help.impl;
+
+public class DocPConst {
+    public static final char	AMPERSAND	= '&';
+    public static final char	COLON		= ':';
+    public static final char	DQUOTE		= '"';
+    public static final char	EQUALS		= '=';
+    public static final char	EXCLAIM		= '!';
+    public static final char	HASH		= '#';
+    public static final char	HORIZBAR	= '_';
+    public static final char	LANGLE		= '<';
+    public static final char	MINUS		= '-';
+    public static final char	NEWLINE		= '\n';
+    public static final char	NINE		= '9';
+    public static final char	NULL		= '\0';
+    public static final char	QUESTION	= '?';
+    public static final char	RANGLE		= '>';
+    public static final char	RETURN		= '\r';
+    public static final char	QUOTE		= '\'';
+    public static final char	SEMICOLON	= ';';
+    public static final char	SLASH		= '/';
+    public static final char	SPACE		= ' ';
+    public static final char	TAB		= '\t';
+    public static final char	ZERO		= '0';
+}
diff --git a/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/DocumentParser.java b/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/DocumentParser.java
new file mode 100644
index 0000000000000000000000000000000000000000..d9f7fbfc4ccc3f006437bf5a6cc26d5abaa5a319
--- /dev/null
+++ b/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/DocumentParser.java
@@ -0,0 +1,1321 @@
+/*
+ * @(#)DocumentParser.java	1.19 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @(#) DocumentParser.java 1.19 - last change made 10/30/06
+ */
+package com.sun.java.help.impl;
+
+/**
+ * This class is designed to be extended for use.  You use it in 
+ * this way:
+ *
+ *	1. instantiate the object, passing an inputStream to the
+ *	   constructor (a string can be passed as well).
+ *
+ *	2. call parse() to start it running.  Parse will return
+ *	   when the eof of file is reached.
+ *
+ *	3. during the parse, each of the following calls will
+ *	   be made.  The extensions should handle the calls as
+ *	   necessary:
+ *
+ *		flush		Called for each contiguous block
+ *				of text.
+ *
+ *		tag		Called for each complete tag
+ *
+ *                         pi	              Called for each PI (non-xml) recognized
+ *
+ *		doctype		Called for a doctype
+ *
+ *		comment		Called for each complete comment
+ *
+ *		errorString	Called for each parse error
+ *
+ *	4. As an extension &xxx; macros can be implemented.  For
+ *	   each unrecognized &xxx; macro, a call to
+ *	   documentAttribute is made that will return a string if
+ *	   the macro name has a value.
+ */
+
+import java.io.CharConversionException;
+import java.io.*;
+import java.util.Hashtable;
+import java.net.*;
+
+public abstract class DocumentParser {
+    static final char EOF = (char)-1;
+
+    protected Reader source;
+    int		readOffset;
+    ScanBuffer	buffer;
+    ScanBuffer	escapeBuffer;
+    ScanBuffer  documentSource;
+    boolean     shouldCacheSource;
+
+    /************************************************************************
+    *****								*****
+    *****		Public interface 				*****
+    *****								*****
+    ************************************************************************/
+
+    public DocumentParser(InputStream in) {
+	source = new MyBufferedReader(new InputStreamReader(in));
+	init();
+    }
+
+    public DocumentParser(Reader src) {
+
+	//..................................................
+	// Check if the Reader src is buffered, and make it buffered
+	// if it's not already
+	//.................................................
+	if (src instanceof MyBufferedReader) {
+	    source = src;
+	} else {
+	    source = new MyBufferedReader(src);
+	}
+	init();
+    }
+
+    public void setInput(Reader src){
+	//source = s;
+	//.................................................. 
+        // Check if the Reader src is buffered, and make it buffered 
+        // if it's not already  
+        //................................................. 
+        if (src instanceof MyBufferedReader) { 
+	    source = src;
+        } else { 
+	    source = new MyBufferedReader(src);
+        }
+    }
+
+    //.....YK..... checking for null InputStream
+
+    public void setInput(InputStream i, String encoding) throws UnsupportedEncodingException
+    {
+	if(i == null) {
+	    source = null;
+	    return;
+	}
+	source = new MyBufferedReader( new InputStreamReader(i, encoding));
+    }
+
+    /*
+     * sets whether to cache document source
+     */
+    public void setShouldCacheSource(boolean state) {
+        shouldCacheSource = state;
+    }
+
+    /*
+     * return String containing the document source (monsanto)
+     * Bug 4058915: File->HTML Source ... menu item shows edited source.
+     */
+    public String getDocumentSource() {
+        if (!shouldCacheSource)
+	    return null;
+        else {
+	    int offset = 
+		(0 == documentSource.length()) ? 0 : documentSource.length() - 1;
+            return new String(documentSource.buf, 0, offset) +"\n";
+        }
+    }
+
+    // ................................. YK (Inline)
+    public void parse() throws IOException {
+        char c = EOF;		// YK: checking for null
+ 
+        buffer.clear();
+        if(source != null) {	// YK: checking for null
+	    c = readChar();
+	}			// YK: checking for null
+        for (;;){
+	    if (c == EOF)
+		break;
+	    if (c == DocPConst.AMPERSAND)
+		c = parseEscape();
+	    else if (c == DocPConst.LANGLE){
+		buffer.flush(this);
+		c = parseTag();
+	    } else {
+		// .................................................
+		// Inlining the data access gives BIG performance win
+		// .................................................
+		// buffer.add(c); // YK: inline
+		if (buffer.buflen >= buffer.buf.length){
+		    char [] x = new char [buffer.buf.length * buffer.scale];
+		    System.arraycopy(buffer.buf, 0, x, 0, buffer.buf.length);
+		    buffer.buf = x;
+		}
+
+		// fixes bug 4056036 - cannot open bat-text files
+		// (monsanto)
+		if (c != DocPConst.RETURN)
+		    buffer.buf[buffer.buflen++] = c;
+
+		// ................................................. 
+		// Inlining the data access gives BIG performance win 
+		// ................................................. 
+
+		//c = readChar(); // YK: inline
+		if(myCount >= mySize) {
+		    try {
+			mySize = source.read(cb, 0, defaultCharBufferSize);
+			if(mySize < 0) {
+			    break;
+			}  
+			if(mySize == 0) {
+			    System.err.println(" DocumentParser::parse() !!!ERROR !!! source.read(...) == 0");
+			    break;
+			}
+			myCount = 0;
+		    } catch (CharConversionException e) {
+			throw e;
+		    } catch (IOException e) {
+			break;
+		    }    
+		}
+		// ..........REMIND - removed .......// readOffset++;
+		if (shouldCacheSource)
+		    documentSource.add(cb[myCount]);
+		c = cb[myCount++];
+	    }
+        }
+        buffer.flush(this);
+    }
+
+
+
+
+    public void parseText() throws IOException {
+	char c;
+
+	tag("PRE", null, false, false);
+
+	buffer.clear();
+	c = readChar();
+	for (;;) {
+	    if (c == EOF)
+		break;
+	    buffer.add(c);
+	    c = readChar();
+	}
+	buffer.flush(this);
+    }
+
+    /**
+     * Invokes flush(). This method is provided so that flush() can 
+     * be protected
+     */
+    protected void callFlush(char [] buf, int offset, int length)
+    {
+	flush(buf, offset, length);
+    }
+
+    /************************************************************************
+    *****								*****
+    *****		Methods to be overridden by subclasses		*****
+    *****								*****
+    ************************************************************************/
+
+    /**
+     * This method creates a block of text for a document.
+     *
+     * It should be overridden by the subclass
+     */
+    abstract protected void flush(char [] buf, int offset, int length);
+
+    /**
+     * This method inserts a comment
+     *
+     * It should be overridden by the subclass
+     */
+    abstract protected void comment(String s);
+
+    /**
+     * This method emits a tag
+     *
+     * It should be overridden by the subclass
+     */
+    abstract protected void tag(String name, TagProperties atts, boolean endTag, boolean emptyTag);
+
+    /**
+     * This method emits a pi
+     *
+     * It should be overridden by the subclass
+     */
+    abstract protected void pi(String target, String data);
+
+    /**
+     * This method emits a doctype.  Internal subset information is discarded
+     *
+     * It should be overridden by the subclass
+     */
+    abstract protected void doctype(String root, String publicId, String systemId);
+
+    /**
+     * This method looks up a &xxx; sequence in the document
+     * properties (this is used for templates).  A return of null
+     * means the proerty is undefined.
+     *
+     * It should be overridden by the subclass
+     */
+    abstract protected String documentAttribute(String name);
+
+    /**
+     * This method inserts a parse error string into the document
+     *
+     * It should be overridden by the subclass
+     */
+    abstract protected void errorString(String s);
+
+    /************************************************************************
+    *****								*****
+    *****		Internal methods				*****
+    *****								*****
+    ************************************************************************/
+
+    private void init() {
+        // .........buffer initialization......................
+        // bigger buffer size gives some performance win
+	buffer = new ScanBuffer(8192, 4);	// YK 
+        // ......... escapeBuffer initialization...............
+        // bigger buffer size gives some performance win
+	escapeBuffer = new ScanBuffer(8192,4);	// YK
+	documentSource = new ScanBuffer(8192,4);	// YK
+	readOffset = 0;
+    }
+
+    protected void findCloseAngleForComment(char c) throws IOException {
+	buffer.add(c);
+	for(;;){
+	    c = readChar();
+	    if (c == DocPConst.RANGLE)
+	    	break;
+	    buffer.add(c);
+	}
+	buffer.add(c);
+	comment(buffer.extract(0));
+	buffer.clear();
+    }
+
+    protected char handleCommentOrDoctype(char c) throws IOException {
+	buffer.add(c);
+	int offset = buffer.length();
+	c = scanIdentifier(c);
+	String name = buffer.extract(offset);
+
+	if (! name.equals("DOCTYPE")) {
+	    findCloseAngleForComment(c);
+	    return readChar();
+	}
+	
+	// a DOCTYPE
+	c = skipWhite(c);
+
+	// The root of the document...
+	offset = buffer.length();
+	c = scanIdentifier(c);
+	String root = buffer.extract(offset);
+
+	c = skipWhite(c);
+	
+	// If no externaID...
+	if (c == DocPConst.RANGLE) {
+
+	    buffer.clear();
+	    return readChar();
+	}
+
+	offset = buffer.length();
+	c = scanIdentifier(c);
+	name = buffer.extract(offset);
+
+	// two forms are valid:
+	// "SYSTEM sysid" and "PUBLIC pubid sysid"
+
+	String publicId = null;
+	String systemId = null;
+
+	if (name.equals("SYSTEM")) {
+	    c = skipWhite(c);
+
+	    offset = buffer.length();
+	    c = scanQuotedString(c);
+	    systemId = buffer.extract(offset);
+
+	    doctype(root, null, systemId);
+
+	    if (c != DocPConst.RANGLE) {
+		findCloseAngleForComment(c);
+	    }
+	    buffer.clear();
+	    return readChar();
+	} else if (name.equals("PUBLIC")) {
+	    c = skipWhite(c);
+
+	    offset = buffer.length();
+	    c = scanQuotedString(c);
+	    publicId = buffer.extract(offset);
+
+	    c = skipWhite(c);
+
+	    offset = buffer.length();
+	    c = scanQuotedString(c);
+	    systemId = buffer.extract(offset);
+
+	    doctype(root, publicId, systemId);
+
+	    if (c != DocPConst.RANGLE) {
+		findCloseAngleForComment(c);
+	    }
+	    buffer.clear();
+	    return readChar();
+	} else {
+	    // we ignore this; altough it is likely an internal DTD subset
+	    if (c != DocPConst.RANGLE) {
+		findCloseAngleForComment(c);
+	    }
+	    findCloseAngleForComment(c);
+
+	    doctype(root, null, null);
+
+	    buffer.clear();
+	    return readChar();
+	}
+    }
+
+
+    protected void setXmlEntities(TagProperties attr) {
+	// Don't do anything for now
+    }
+
+    protected char parseTag() throws IOException {
+	char		c;
+	String		name;
+	TagProperties	attributes;
+	int		offset;
+	int		tagStartOffset;
+	boolean		endTag;
+	boolean		emptyTag;
+
+	/**
+	 * Comments are handled in the following way:
+	 * 1) If the first character is "!" AND  NOT followed by "--" 
+	 *    then everything is a comment till the subsequent closing 
+	 *    angle bracket.
+	 * 2) If the first character is "!" AND is followed by "--" then
+	 *    everything till "--" followed by a closing angle bracket
+	 *    is marked as a comment. This can include other closing and
+	 *    opening angle brackets.
+	 *
+	 * N.B Netscape follows the above two rules with a caveat to rule
+	 *     2 from above. If it does not find "--" followed by a closing
+	 *     angle bracket in the rest of the document, it behaves as rule
+	 *     1 i.e the subsequent closing angle bracket is taken as the
+	 *     end of the comment.
+	 *
+	 * Xml entities are handled in the following way:
+	 * 1) If the first character is "?" AND is followed by "xml" 
+	 *    then everything is a xml entity till the subsequent closing 
+	 *    "?" followed by an angle bracket.
+	 *
+	 */
+
+	buffer.clear();
+	tagStartOffset = 0;
+	c = DocPConst.LANGLE;
+	buffer.add(DocPConst.LANGLE);
+	c = readChar();
+	if (c == DocPConst.EXCLAIM){		//  comment follows
+	    int resetPos = 0;
+	    buffer.add(DocPConst.EXCLAIM);
+	    // =-= jd BEGIN HACK
+	    // Taking the check for - out since Netscape just uses <!
+	    // to mark a comment
+	    c = readChar();
+	    if (c != DocPConst.MINUS){
+		// a shorthand comment or a DOCTYPE
+		return handleCommentOrDoctype(c);
+	    }
+	    buffer.add(c);      // =-= jd Added this line
+	    c = readChar();
+	    if (c != DocPConst.MINUS){	// it's still a "shorthand" comment
+		findCloseAngleForComment(c);
+		return readChar();
+	    }
+	    buffer.add(c);     // =-= jd Added this line
+	    // just in case of the NB comment from above, set a fallback pos
+	    resetPos = buffer.length();
+	    // source.reset() doesn't work at all :(
+	    // without that, we can't do NB on comments. - the
+	    // comment goes to EOF, unless it encounters "-->"
+	    //if (source.markSupported()) {
+	    //  resetPos = buffer.length();
+	    //  try {
+	    //	source.mark(64);	// pass in readAheadLimit
+	    //  } catch (IOException e){
+	    //  }
+	    //}
+
+	    // handled "shorthand" comments - now need to look for "-->"
+	    int nDash = 0;
+	    for(;;) {
+		c = readChar();
+		if (c == EOF) {
+		    commentEOFError(resetPos);
+		    break;
+		}
+		if (c != DocPConst.MINUS) {
+		    buffer.add(c);
+		    continue;
+		}
+		while (c == DocPConst.MINUS) {
+		    buffer.add(c);
+		    nDash ++;
+		    c = readChar();
+		}
+		if (c == EOF) {
+		    commentEOFError(resetPos);
+		    break;
+		}
+		buffer.add(c);
+		if ((nDash >= 2) && (c == DocPConst.RANGLE)) {
+		    comment(buffer.extract(0));
+		    buffer.clear();
+		    return readChar();
+		}
+		nDash = 0;
+	    }
+	}
+	if (c == DocPConst.QUESTION){		//  xml & PI declarations follows
+	    int resetPos = 0;
+	    StringBuffer target = new StringBuffer();
+	    buffer.add(DocPConst.QUESTION);
+	    while (((c = readChar()) != DocPConst.DQUOTE) &&
+		   c != DocPConst.SPACE  &&
+		   c != DocPConst.TAB    &&
+		   c != DocPConst.NEWLINE &&
+		   c != DocPConst.RANGLE) {
+		buffer.add(c);
+		target.append(c);
+	    }
+
+	    if (! target.toString().equals("xml")) {
+		// we have a PI ...
+		buffer.clear();	// reset the buffer
+		while (true) {
+		    while ((c = readChar()) != DocPConst.QUESTION &&
+			   c != EOF) {
+			buffer.add(c);
+		    }
+		    if (c == EOF) {
+			eofError();
+			return readChar();
+		    }
+		    c = readChar();
+		    if (c != DocPConst.RANGLE &&
+			c != EOF) {
+			buffer.add(DocPConst.QUESTION);
+			buffer.add(c);
+		    }
+		    if (c == EOF) {
+			eofError();
+			return readChar();
+		    } else {
+			pi(target.toString(), buffer.extract(0));
+			return readChar();
+		    }
+		}
+	    }
+	    // discard that target
+	    target = null;
+
+	    // OK so far 
+	    //
+	    // try to find the attributes
+	    c = readChar();
+	    attributes = null;
+	    for (;;){
+		c = skipWhite(c);
+		if (c == EOF){
+		    eofError();
+		    return c;
+		}
+		if (c == DocPConst.QUESTION)
+		    break;
+
+		offset = buffer.length();
+		c = scanIdentifier(c);
+		if (offset == buffer.length()){
+		    error("Expecting an attribute");
+		    skipToCloseAngle(c);
+		    return readChar();
+		}
+		String attname = buffer.extract(offset);
+		c = skipWhite(c);
+		if (attributes == null)
+		    attributes = new TagProperties();
+		String	attvalue;
+		if (c == DocPConst.EQUALS) {		// parsing attribute value
+		    buffer.add(c);
+		    c = readChar();
+		    int	voff;
+		    // ignore whitespace between the EQUALS and the attr value
+		    // because netscape does	(bug#4045870)
+		    c = skipWhite(c);
+		    // delimit on RANGLE and LANGLE in case of incomplete line
+		    if (c == DocPConst.QUESTION || c == DocPConst.LANGLE ){
+			attvalue = "";
+		    } else if (c == DocPConst.DQUOTE){
+			buffer.add(c);
+			voff = buffer.length();
+			for (;;){
+			    c = readChar();
+			    if (c == EOF){
+				eofError();
+				return c;
+			    }
+			    if (c == DocPConst.DQUOTE)
+				break;
+			    // transform &
+			    if (c == DocPConst.AMPERSAND)
+				c = parseEscape();
+			    buffer.add(c);
+			}
+			attvalue = buffer.extract(voff);
+			buffer.add(c);
+			c = readChar();
+		    } else {
+			voff = buffer.length();
+			buffer.add(c);
+			for (;;){
+			    c = readChar();
+			    if (c == EOF){
+				eofError();
+				return c;
+			    }
+			    if (c == DocPConst.DQUOTE ||
+				c == DocPConst.SPACE  ||
+				c == DocPConst.TAB    ||
+				c == DocPConst.NEWLINE ||
+				c == DocPConst.QUESTION)
+				break;
+			    // transform &
+			    if (c == DocPConst.AMPERSAND)
+				c = parseEscape();
+			    buffer.add(c);
+			}
+			attvalue = buffer.extract(voff);
+		    }
+		} else {
+		    attvalue = "true";
+		}
+		attributes.put(attname, attvalue);
+	    }
+	    c = readChar();
+	    if (c == EOF) {
+		eofError();
+		return readChar();
+	    }
+	    c = skipWhite(c);
+	    buffer.add(c);
+	    if ((c == DocPConst.RANGLE)) {
+		setXmlEntities(attributes);
+		buffer.clear();
+		return readChar();
+	    } else {
+		error ("Expecting ?>");
+		skipToCloseAngle(c);
+		return readChar();
+	    }
+	}
+	c = skipWhite(c);
+	if (c == EOF){
+	    eofError();
+	    return c;
+	}
+	if (c == DocPConst.SLASH){
+	    buffer.add(c);
+	    c = skipWhite(readChar());
+	    endTag = true;
+	    emptyTag = false;
+	} else {
+	    endTag = false;
+	    emptyTag = false;
+	}
+	offset = buffer.length();
+	c = scanIdentifier(c);
+	name = buffer.extract(offset);
+	attributes = null;
+	for (;;){
+	    c = skipWhite(c);
+	    if (c == EOF){
+		eofError();
+		return c;
+	    }
+
+	    if (c == DocPConst.RANGLE)
+		break;
+
+	    if (c == DocPConst.SLASH) {
+		buffer.add(c);
+		c = readChar();
+		if (c == DocPConst.RANGLE) {
+		    endTag = true;
+		    emptyTag = true;
+		    break;
+		} else {
+		    error("Expecting />");
+		    skipToCloseAngle(c);
+		    return readChar();
+		}
+	    }
+
+	    if (c == DocPConst.LANGLE)  {
+
+		// this could be a comment inside a tag e.g. 
+		// <TABLE width=500 <!-- border=5 --> color="e0e0e0"
+		// right now we will ignore the comment and
+		// close the tag as Netscape does.
+
+		// OR
+
+		// our learned HTML author has forgotten to
+		// close the tag. e.g.
+		// <TABLE width=500 border=5 color="e0e0e0"
+		// <CAPTION>....
+
+		tag(name, attributes, endTag, false);
+		buffer.clear();
+		return (DocPConst.LANGLE);
+	    }
+
+	    offset = buffer.length();
+	    c = scanIdentifier(c);
+	    if (offset == buffer.length()){
+		error("Expecting an attribute (2)");
+		skipToCloseAngle(c);
+		return readChar();
+	    }
+	    String attname = buffer.extract(offset);
+	    c = skipWhite(c);
+	    if (attributes == null)
+		attributes = new TagProperties();
+	    String	attvalue;
+	    if (c == DocPConst.EQUALS) {		// parsing attribute value
+		buffer.add(c);
+		c = readChar();
+		int	voff;
+		// ignore whitespace between the EQUALS and the attr value
+		// because netscape does	(bug#4045870)
+		c = skipWhite(c);
+		// delimit on RANGLE and LANGLE in case of incomplete line
+		if (c == DocPConst.RANGLE || c == DocPConst.LANGLE ){
+		    attvalue = "";
+		} else if (c == DocPConst.DQUOTE){
+		    buffer.add(c);
+		    voff = buffer.length();
+		    for (;;){
+			c = readChar();
+			if (c == EOF){
+			    eofError();
+			    return c;
+			}
+			if (c == DocPConst.DQUOTE)
+			    break;
+			// transform &
+			if (c == DocPConst.AMPERSAND)
+			    c = parseEscape();
+			buffer.add(c);
+		    }
+		    attvalue = buffer.extract(voff);
+		    buffer.add(c);
+		    c = readChar();
+		} else {
+		    voff = buffer.length();
+		    buffer.add(c);
+		    for (;;){
+			c = readChar();
+			if (c == EOF){
+			    eofError();
+			    return c;
+			}
+			if (c == DocPConst.DQUOTE ||
+			    c == DocPConst.SPACE  ||
+			    c == DocPConst.TAB    ||
+			    c == DocPConst.NEWLINE ||
+			    c == DocPConst.RANGLE)
+			    break;
+			// transform &
+			if (c == DocPConst.AMPERSAND)
+			    c = parseEscape();
+			buffer.add(c);
+		    }
+		    attvalue = buffer.extract(voff);
+		}
+	    } else {
+		attvalue = "true";
+	    }
+	    attributes.put(attname, attvalue);
+	}
+	tag(name, attributes, endTag, emptyTag);
+	buffer.clear();
+	return readChar();
+    }
+
+
+    protected char parseEscape() throws IOException {
+	char	c;
+	int	offset;
+
+	offset = buffer.length();
+	buffer.add(DocPConst.AMPERSAND);
+	c = readChar();
+	if (c == EOF){
+	    generateError(offset);
+	    return c;
+	}
+	if (c == DocPConst.HASH){
+	    int	x;
+
+	    x = 0;
+	    for (;;){
+		c = readChar();
+		if (c == EOF){
+		    generateError(offset);
+		    return c;
+		} else if (c == DocPConst.SEMICOLON) {
+		    c = DocPConst.NULL;
+		    break;
+		} else if (!Character.isDigit(c)){
+		    if (x > 0) {
+			break;
+		    } else {
+			error("Expecting a digit");
+			generateError(offset);
+			return c;
+		    }
+		}
+		buffer.add(c);
+		x = x * 10 + Character.digit(c, 10);
+	    }
+	    buffer.reset(offset);
+	    buffer.add((char)x);
+	} else if (Character.isLowerCase(c) ||
+		   Character.isUpperCase(c)){
+	    if (entities == null)
+		initEntities();
+
+	    escapeBuffer.clear();
+	    escapeBuffer.add(c);
+	    for (;;){
+		buffer.add(c);
+		c= readChar();
+		if (c == EOF){
+		    generateError(offset);
+		    return c;
+		}
+		if (Character.isLowerCase(c) ||
+		    Character.isUpperCase(c)){
+		    escapeBuffer.add(c);
+		    if (entities.get(escapeBuffer.extract(0)) != null) {
+			c = readChar();
+			if (c == DocPConst.SEMICOLON)
+			    c = DocPConst.NULL;
+			break;
+		    }
+		} else if (c == DocPConst.SEMICOLON) {
+		    c = DocPConst.NULL;
+		    break;
+		} else {
+		    error("Expecting a letter");
+		    generateError(offset);
+		    return c;
+		}
+	    }
+	    String s = escapeBuffer.extract(0);
+
+	    buffer.reset(offset);
+
+	    Character x = (Character)entities.get(s);
+
+	    if (x != null){
+		return x.charValue();
+	    } else {
+		String a = documentAttribute(s);
+
+		if (a != null){
+		    int	i;
+
+		    for (i = 0; i < a.length(); i++)
+			buffer.add(a.charAt(i));
+		}
+	    }
+	} else {
+	    error("Expecting a letter o");
+	    generateError(offset);
+	    return c;
+	}
+	if (c != DocPConst.NULL)
+	    return c;
+	else
+	    return readChar();
+    }
+
+    Hashtable entities;
+
+    protected void initEntities() {
+	entities = new Hashtable();
+
+	entities.put("quot",	new Character(DocPConst.DQUOTE));
+	entities.put("amp",	new Character(DocPConst.AMPERSAND));
+	entities.put("gt",	new Character(DocPConst.RANGLE));
+	entities.put("lt",	new Character(DocPConst.LANGLE));
+
+	entities.put("nbsp",	new Character((char)160));
+
+	entities.put("copy",	new Character((char)169));
+
+	entities.put("Agrave",	new Character((char)192));
+	entities.put("Aacute",	new Character((char)193));
+	entities.put("Acirc",	new Character((char)194));
+	entities.put("Atilde",	new Character((char)195));
+	entities.put("Auml",	new Character((char)196));
+	entities.put("Aring",	new Character((char)197));
+	entities.put("AElig",	new Character((char)198));
+	entities.put("Ccedil",	new Character((char)199));
+	entities.put("Egrave",	new Character((char)200));
+	entities.put("Eacute",	new Character((char)201));
+	entities.put("Ecirc",	new Character((char)202));
+	entities.put("Euml",	new Character((char)203));
+	entities.put("Igrave",	new Character((char)204));
+	entities.put("Iacute",	new Character((char)205));
+	entities.put("Icirc",	new Character((char)206));
+	entities.put("Iuml",	new Character((char)207));
+
+	entities.put("Ntilde",	new Character((char)209));
+	entities.put("Ograve",	new Character((char)210));
+	entities.put("Oacute",	new Character((char)211));
+	entities.put("Ocirc",	new Character((char)212));
+	entities.put("Otilde",	new Character((char)213));
+	entities.put("Ouml",	new Character((char)214));
+
+	entities.put("Oslash",	new Character((char)216));
+	entities.put("Ugrave",	new Character((char)217));
+	entities.put("Uacute",	new Character((char)218));
+	entities.put("Ucirc",	new Character((char)219));
+	entities.put("Uuml",	new Character((char)220));
+	entities.put("Yacute",	new Character((char)221));
+	entities.put("THORN",	new Character((char)222));
+	entities.put("szlig",	new Character((char)223));
+	entities.put("agrave",	new Character((char)224));
+	entities.put("aacute",	new Character((char)225));
+	entities.put("acirc",	new Character((char)226));
+	entities.put("atilde",	new Character((char)227));
+	entities.put("auml",	new Character((char)228));
+	entities.put("aring",	new Character((char)229));
+	entities.put("aelig",	new Character((char)230));
+	entities.put("ccedil",	new Character((char)231));
+	entities.put("egrave",	new Character((char)232));
+	entities.put("eacute",	new Character((char)233));
+	entities.put("ecirc",	new Character((char)234));
+	entities.put("euml",	new Character((char)235));
+	entities.put("igrave",	new Character((char)236));
+	entities.put("iacute",	new Character((char)237));
+	entities.put("icirc",	new Character((char)238));
+	entities.put("iuml",	new Character((char)239));
+	entities.put("eth",	new Character((char)240));
+	entities.put("ntilde",	new Character((char)241));
+	entities.put("ograve",	new Character((char)242));
+	entities.put("oacute",	new Character((char)243));
+	entities.put("ocirc",	new Character((char)244));
+	entities.put("otilde",	new Character((char)245));
+	entities.put("ouml",	new Character((char)246));
+
+	entities.put("oslash",	new Character((char)248));
+	entities.put("ugrave",	new Character((char)249));
+	entities.put("uacute",	new Character((char)250));
+	entities.put("ucirc",	new Character((char)251));
+	entities.put("uuml",	new Character((char)252));
+	entities.put("yacute",	new Character((char)253));
+	entities.put("thorn",	new Character((char)254));
+	entities.put("yuml",	new Character((char)255));
+    }
+
+    // ....................................................
+    // YK: optimization: Inlining
+    // ....................................................
+
+    protected char scanIdentifier(char c) throws IOException {
+        for (;;) {
+	    if (! (
+		   c == DocPConst.HORIZBAR  ||
+		   c == DocPConst.COLON ||
+		   (c >= DocPConst.ZERO && c <= DocPConst.NINE)		||
+		   Character.isLetter(c)
+				// Used to be Character.isUpperCase(c)
+		      )
+		   ) {
+		break;
+	    }
+	    // ............................................
+	    // Inlining again an again
+	    // ............................................
+	    // buffer.add(c); // YK: inline
+	    if (buffer.buflen >= buffer.buf.length){
+		char [] x = new char [buffer.buf.length * buffer.scale];
+		System.arraycopy(buffer.buf, 0, x, 0, buffer.buf.length);
+		buffer.buf = x;
+	    }
+
+	    // ............................................
+	    // Inlining again an again 
+	    // ............................................
+	    buffer.buf[buffer.buflen++] = c;
+ 
+	    //c = readChar(); // YK: inline
+	    if(myCount >= mySize) {
+		try {
+		    mySize = source.read(cb, 0, defaultCharBufferSize);
+		    if(mySize < 0) {
+			break;
+		    }
+		    if(mySize == 0) {
+			System.err.println(" DocumentParser::scanIdentifier() !!!ERROR !!! source.read(...) == 0");
+			break;
+		    }
+		    myCount = 0;
+		} catch (CharConversionException e) {
+		    throw e;
+		} catch (IOException e) {
+		    break;
+		}
+	    }
+	    //...........REMIND............removed......// readOffset++;
+	    if (shouldCacheSource)
+		documentSource.add(cb[myCount]);
+	    c = cb[myCount++];
+        }
+        return c;
+    }
+
+
+    // ......................................................
+    // Scan a single or double quoted string
+    // ......................................................
+    protected char scanQuotedString(char c) throws IOException {
+	c = skipWhite(c);
+	if (c == DocPConst.DQUOTE) {
+	    for (;;) {
+		c = readChar();
+		if (c == DocPConst.DQUOTE ||
+		    c == DocPConst.RANGLE) {
+		    break;
+		}
+		buffer.add(c);
+	    }
+	    return readChar();
+	} else if (c == DocPConst.QUOTE) {
+	    for (;;) {
+		c = readChar();
+		if (c == DocPConst.QUOTE ||
+		    c == DocPConst.RANGLE) {
+		    break;
+		}
+		buffer.add(c);
+	    }
+	    return readChar();
+	} else {
+	    return c;
+	}
+    }
+    
+    // ......................................................
+    //  This whole method is inlined including the data reading
+    // ................. YK: Inline
+    protected char skipWhite(char c) throws IOException {
+	while (c == DocPConst.SPACE  ||
+	       c == DocPConst.RETURN ||
+	       c == DocPConst.TAB    ||
+	       c == DocPConst.NEWLINE)   {
+	    // ............................................
+	    // Inlining again an again 
+	    // ............................................
+	    // buffer.add(c); // YK: inline
+	    if (buffer.buflen >= buffer.buf.length){
+		char [] x = new char [buffer.buf.length * buffer.scale];
+		System.arraycopy(buffer.buf, 0, x, 0, buffer.buf.length);
+		buffer.buf = x;
+	    }
+	    buffer.buf[buffer.buflen++] = c;
+ 
+	    //c = readChar(); // YK: inline
+	    // ............................................ 
+	    // Inlining again an again  
+	    // ............................................ 
+
+	    if(myCount >= mySize) {
+		try {
+		    mySize = source.read(cb, 0, defaultCharBufferSize);
+		    if(mySize < 0) {
+			break;
+		    }
+		    if(mySize == 0) {
+			System.err.println(" DocumentParser::parse() !!!ERROR !!! source.read(...) == 0");
+			break;
+		    }
+		    myCount = 0;
+		} catch (CharConversionException e) {
+		    throw e;
+		} catch (IOException e) {
+		    break;
+		}
+	    }
+	    //...........REMIND............removed......// readOffset++;
+	    if (shouldCacheSource)
+		documentSource.add(cb[myCount]);
+	    c = cb[myCount++];
+	}
+	return c;
+    }
+
+
+    // ................................................................
+    // The readChar method is heavily inlined
+    // (all the calls to sychronized read() are removed)
+    // The read() also creates on char array every time !!! - VERY SLOW
+    // YK 
+    // .................................................................
+    int defaultCharBufferSize = 8192; 
+    char cb[] = new char[defaultCharBufferSize]; 
+    int mySize =  0;
+    int myCount = 0;
+    protected char readChar() throws IOException {
+	if(myCount  >=mySize) {
+	    try {
+                mySize = source.read(cb, 0, defaultCharBufferSize);
+		if(mySize < 0) {
+		    return EOF;
+		}
+		if(mySize == 0) {
+		    System.err.println(" DocumentParser::readChar() !!!ERROR !!! source.read(...) == 0");
+		    return EOF;
+		}
+		myCount = 0;
+	    } catch (CharConversionException e) {
+		throw e;
+	    } catch (IOException e) {
+		return EOF;
+	    }
+	}
+	//...........REMIND............removed......// readOffset++;
+	if (shouldCacheSource)
+	    documentSource.add(cb[myCount]);
+	return cb[myCount++];
+    }  
+
+    /**
+     * This method is called when parsing a tag and an error is
+     * encountered.  It skips to the closing angle bracket, 
+     * treating the entire tag as error text.  The generateError
+     * call at the end stuffs the full tag into the document
+     * as an error.
+     */
+
+    // YK: Inlining
+    // ................................................................ 
+    // The skipToCloseAngle method is heavily inlined
+    // (all the calls to sychronized read() are removed) 
+    // The read() also creates on char array every time !!! - VERY SLOW   
+    // YK 
+    // ................................................................. 
+
+    protected void skipToCloseAngle(char c) throws IOException {
+        for (;;) { 
+	    //buffer.add(c);  
+
+
+            if (buffer.buflen >= buffer.buf.length){
+                char [] x = new char [buffer.buf.length * buffer.scale];
+                System.arraycopy(buffer.buf, 0, x, 0, buffer.buf.length);
+                buffer.buf = x;
+	    }
+	    buffer.buf[buffer.buflen++] = c;
+
+	    if (c == DocPConst.RANGLE)  {
+		break;
+	    }
+
+
+
+	    //c = readChar();
+
+
+	    if(myCount >= mySize) {
+		try {
+		    mySize = source.read(cb, 0, defaultCharBufferSize);
+		    if(mySize < 0) {
+                        break;
+		    }
+		    if(mySize == 0) {
+                        System.err.println(" DocumentParser::skipToCloseAngle() !!!ERROR !!! source.read(...) == 0");
+                        break;
+		    }
+		    myCount = 0;
+		} catch (CharConversionException e) {
+		    throw e;
+		} catch (IOException e) {
+		    break;
+		}
+	    }
+	    //...........REMIND............removed......// readOffset++;
+	    c = cb[myCount++];
+        }
+
+
+        generateError(0);
+    }
+
+    protected void generateError(int offset) {
+	String s = buffer.extract(offset);
+
+	buffer.reset(offset);
+	buffer.flush(this);
+	errorString(s);
+    }
+
+    protected void commentEOFError(int resetTo) {
+	/*  tried to use source.reset, but didn't work this way...
+	    // for some reason, this isn't resetting the source (BufferedReader)
+	    source.reset();
+	    buffer.reset(resetTo);
+	    char c = readChar();
+	    if (c != DocPConst.RANGLE) 
+	    findCloseAngleForComment(c);
+	    else {
+	    buffer.add(c);
+	    comment(buffer.extract(0));
+	    buffer.clear();
+	    }
+	    } catch (IOException e) {
+	    }
+	    */
+	//System.err.println("DocumentParser:: comment went past end of buffer!");
+	eofError();
+    }
+
+    protected void eofError() {
+	error("Unexpected end of file");
+	generateError(0);
+    }
+
+    void error(String s) {
+	System.err.println("DocumentParser Error: "+s);
+    }
+} // class DocumentParser
+
+class ScanBuffer {
+    char []	buf;
+    int		buflen;
+    int scale = 2;
+
+    ScanBuffer() {
+	buf = new char [ 256 ];
+    }
+
+    //...........................................................
+    // YK -extra constructor with the initial buffer size
+    //...........................................................
+    ScanBuffer(int l, int s) {
+        buf = new char [l];
+	scale = s;
+    }
+
+    protected void clear() {
+	buflen = 0;
+    }
+ 
+    protected void reset(int offset) {
+	buflen = offset;
+    }
+
+    protected void flush(DocumentParser owner) {
+	if (buflen > 0){
+	    owner.callFlush(buf, 0, buflen);
+	    buflen = 0;
+	}
+    }
+
+    protected void add(char c) {
+	if (buflen >= buf.length){
+	    char [] x = new char [buf.length * scale];
+	    System.arraycopy(buf, 0, x, 0, buf.length);
+	    buf = x;
+	}
+	buf[buflen++] = c;
+    }
+
+    protected int length() {
+	return buflen;
+    }
+
+    public String toString() {
+ 	return "ScanBuffer, buf = " + buf + ", buflen = " + buflen;
+    } 
+
+    //....................................................
+    // YK: optimized creating new strings
+    // without any data copying (big performance win)
+    // as this method is called allover the place
+    //....................................................
+   
+    protected String extract(int offset) {
+	return new String(buf, offset, buflen - offset);
+    }
+
+} // class ScanBuffer
+
+
+// YK: This class is created to fix NullPointerException
+// in BufferedReader::read(...) having lock == null
+
+class MyBufferedReader extends BufferedReader {
+    public MyBufferedReader(Reader in, int sz) { super(in, sz); }  
+    public MyBufferedReader(Reader in) { super(in); }  
+    public int read(char cbuf[], int off, int len) throws IOException {
+	if(lock == null) {
+	    //System.err.println("read(): -------------------lock == null");
+	    return -1;
+	}
+	//System.err.println("read(): +++++++++++++++++++lock = " + lock);
+	return super.read(cbuf, off, len);
+    }
+}
diff --git a/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/HeaderParser.java b/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/HeaderParser.java
new file mode 100644
index 0000000000000000000000000000000000000000..94ad203d18a1f6b32bf0e9e2339651f9bbf7b249
--- /dev/null
+++ b/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/HeaderParser.java
@@ -0,0 +1,182 @@
+/*
+ * @(#)HeaderParser.java	1.4 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @(#) HeaderParser.java 1.4 - last change made 10/30/06
+ */
+
+package com.sun.java.help.impl;
+
+/**
+ * This class provides is useful for the nightmare of parsing multi-part 
+ * HTTP/RFC822 headers sensibly:
+ * <p>
+ * <pre>
+ * From a String like: 'timeout=15, max=5'
+ * create an array of Strings:
+ * { {"timeout", "15"},
+ *   {"max", "5"}
+ * }
+ * From one like: 'Basic Realm="FuzzFace" Foo="Biz Bar Baz"'
+ * create one like (no quotes in literal):
+ * { {"basic", null},
+ *   {"realm", "FuzzFace"}
+ *   {"foo", "Biz Bar Baz"}
+ * }
+ * keys are converted to lower case, vals are left as is....
+ * </pre>
+ *
+ * @version	1.4	10/30/06
+ * @author	Dave Brown
+ * @author	Roger D. Brinkley
+ */ 
+
+
+public class HeaderParser {
+
+    /* table of key/val pairs - maxes out at 10!!!!*/
+    String raw;
+    String[][] tab;
+    
+    public HeaderParser(String raw) {
+	this.raw = raw;
+	tab = new String[10][2];
+	parse();
+    }
+
+    private void parse() {
+	
+	if (raw != null) {
+	    raw = raw.trim();
+	    char[] ca = raw.toCharArray();
+	    int beg = 0, end = 0, i = 0;
+	    boolean inKey = true;
+	    boolean inQuote = false;
+	    int len = ca.length;
+	    while (end < len) {
+		char c = ca[end];
+		if (c == '=') { // end of a key
+		    tab[i][0] = new String(ca, beg, end-beg).toLowerCase();
+		    inKey = false;
+		    end++;
+		    beg = end;
+		} else if (c == '\"') {
+		    if (inQuote) {
+			tab[i++][1]= new String(ca, beg, end-beg);
+			inQuote=false;
+			do {
+			    end++;
+			} while (end < len && (ca[end] == ' ' || ca[end] == ','));
+			inKey=true;
+			beg=end;
+		    } else {
+			inQuote=true;
+			end++;
+			beg=end;
+		    }
+		} else if (c == ' ' || c == ',') { // end key/val, of whatever we're in
+		    if (inQuote) {
+			end++;
+			continue;
+		    } else if (inKey) {
+			tab[i++][0] = (new String(ca, beg, end-beg)).toLowerCase();
+		    } else {
+			tab[i++][1] = (new String(ca, beg, end-beg));
+		    }
+		    while (end < len && (ca[end] == ' ' || ca[end] == ',')) {
+			end++;
+		    }
+		    inKey = true;
+		    beg = end;
+		} else {
+		    end++;
+		}
+	    } 
+	    // get last key/val, if any
+	    if (--end > beg) {
+		if (!inKey) {
+		    if (ca[end] == '\"') {
+			tab[i++][1] = (new String(ca, beg, end-beg));
+		    } else {
+			tab[i++][1] = (new String(ca, beg, end-beg+1));
+		    }
+		} else {
+		    tab[i][0] = (new String(ca, beg, end-beg+1)).toLowerCase();
+		}
+	    } else if (end == beg) {
+		if (!inKey) {
+		    if (ca[end] == '\"') {
+			tab[i++][1] = String.valueOf(ca[end-1]);
+		    } else {
+			tab[i++][1] = String.valueOf(ca[end]);
+		    }
+		} else {
+		    tab[i][0] = String.valueOf(ca[end]).toLowerCase();
+		}
+	    } 
+	}
+	
+    }
+
+    public String findKey(int i) {
+	if (i < 0 || i > 10)
+	    return null;
+	return tab[i][0];
+    }
+
+    public String findValue(int i) {
+	if (i < 0 || i > 10)
+	    return null;
+	return tab[i][1];
+    }
+
+    public String findValue(String key) {
+	return findValue(key, null);
+    }
+
+    public String findValue(String k, String Default) {
+	if (k == null)
+	    return Default;
+	k.toLowerCase();
+	for (int i = 0; i < 10; ++i) {
+	    if (tab[i][0] == null) {
+		return Default;
+	    } else if (k.equals(tab[i][0])) {
+		return tab[i][1];
+	    }
+	}
+	return Default;
+    }
+
+    public int findInt(String k, int Default) {
+	try {
+	    return Integer.parseInt(findValue(k, String.valueOf(Default)));
+	} catch (Throwable t) {
+	    return Default;
+	}
+    }
+ }
diff --git a/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/JHSecondaryViewer.java b/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/JHSecondaryViewer.java
new file mode 100644
index 0000000000000000000000000000000000000000..be62cd1d1eb535505d576febff8398145a5d94cc
--- /dev/null
+++ b/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/JHSecondaryViewer.java
@@ -0,0 +1,948 @@
+/*
+ * @(#)JHSecondaryViewer.java	1.25 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.java.help.impl;
+
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Rectangle;
+import java.awt.Point;
+import java.awt.Color;
+import java.awt.FontMetrics;
+import java.awt.Font;
+import javax.swing.Icon;
+import javax.swing.ImageIcon;
+import javax.swing.JButton;
+import javax.swing.LookAndFeel;
+import javax.swing.SwingUtilities;
+import javax.swing.UIManager;
+import javax.swing.plaf.basic.BasicButtonUI;
+import javax.swing.border.EmptyBorder;
+import javax.swing.text.View;
+import javax.swing.text.Element;
+import javax.swing.text.AttributeSet;
+import javax.swing.text.StyleConstants;
+import javax.swing.text.Document;
+import javax.swing.text.SimpleAttributeSet;
+import javax.swing.text.html.HTMLDocument;
+import javax.swing.text.html.StyleSheet;
+import javax.help.*;
+import javax.help.Map.ID;
+import java.awt.event.*;
+import java.awt.Dimension;
+import java.awt.Insets;
+import java.net.*;
+import java.util.Hashtable;
+import java.beans.PropertyChangeEvent;
+import java.util.Enumeration;
+import java.awt.Cursor;
+
+/**
+ * This class is a secondary viewer to be included in HTML content within
+ * JHContentViewer. The ViewerType can either be a SecondaryWindow or a Popup.
+ * Activation is done be either a Button or a mouse enabled Label. Both Button
+ * and Label support Text, Icon, or Text and Icon.
+ * <p>
+ * To use this class within HTML content use the &ltobject&gt tag. Below is an
+ * example usage:
+ * <p><pre>
+ * &ltobject CLASSID="java:com.sun.java.help.impl.JHSecondaryViewer"&gt
+ * &ltparam name="content" value="secondary_contents.html"&gt
+ * &ltparam name="viewerActivator" value="javax.help.LinkLabel"&gt
+ * &ltparam name="viewerStyle" value="javax.help.Popup"&gt
+ * &ltparam name="viewerSize" value="300,400"&gt
+ * &ltparam name="text" value="Click here"&gt
+ * &ltparam name="textFontFamily" value="SansSerif"&gt
+ * &ltparam name="textFontSize" value="x-large"&gt
+ * &ltparam name="textFontWeight" value="plain"&gt
+ * &ltparam name="textFontStyle" value="italic"&gt
+ * &ltparam name="textColor" value="red"&gt
+ * &lt/object&gt
+ * </pre><p>
+ * Valid parameters are:
+ * <ul>
+ * <li>content - a valid url, can be relative to the current viewer
+ * @see setContent
+ * <li>id - a valid id from the current HelpSet
+ * @see setId
+ * <li>viewerName - the name of the SecondaryWindow to display the content in
+ * @see setViewerName
+ * <li>viewerActivator - the activator type for the viewer.
+ * Either "javax.help.LinkButton" or "javax.help.LinkLabel"
+ * @see setViewerActivator
+ * <li>viewerStyle - the style of the viewer. Either "SecondaryWindow" or "Popup"
+ * @see setViewerStyle
+ * <li>viewerLocation - the x,y coordinates applied to a secondary window.
+ * @see setViewerLocation
+ * <li>viewerSize - the width, height applied to a viewer.
+ * @see setViewerSize
+ * <li>iconByName - the url or id of a icon to be displayed in the activator.
+ * The url is relative to the base address of the document
+ * @see setIconByName
+ * <li>text - the text of the activator
+ * @see setText
+ * <li>textFontFamily - the font family of the activator text
+ * @see setTextFontFamily
+ * <li>textFontSize - the size of the activator text font. Size is specified
+ * in a css termonolgy. See the setTextFontSize for acceptable syntax
+ * @see setTextFontSize
+ * <li>textFontWeight - the activator text font weight
+ * @see setTextFontWeight
+ * <li>textFontStyle - the activator text font style
+ * @see setTextFontStyle
+ * <li>textColor - the activator text color
+ * @see setTextColor
+ * <ul>
+ * @see JHSecondaryWindowBeanInfo
+ *
+ * @author Roger D. Brinkley
+ * @version	1.25	10/30/06
+ */
+public class JHSecondaryViewer extends JButton implements ActionListener, ViewAwareComponent {
+    
+    private View myView;
+    private HelpSet hs;
+    private SimpleAttributeSet textAttribs;
+    private URL base;
+    private HTMLDocument doc;
+
+    static public String POPUP = "javax.help.Popup";
+    static public String SECONDARY_WINDOW = "javax.help.SecondaryWindow";
+    static public String LINK_BUTTON = "javax.help.LinkButton";
+    static public String LINK_LABEL = "javax.help.LinkLabel";
+    private final static String buttonPropertyPrefix = "Button" + ".";
+    private final static String editorPropertyPrefix = "EditorPane" + ".";
+    private final static Cursor handCursor =
+	Cursor.getPredefinedCursor(Cursor.HAND_CURSOR);
+    static private Component container;
+
+    private Cursor origCursor;
+
+    /**
+     * Create a secondaryviewer. By default the viewer creates a button with
+     * the text of ">"
+     */
+    public JHSecondaryViewer() {
+	super();
+	setText(">");
+	setMargin(new Insets(0,0,0,0));
+	createLinkButton();
+	addActionListener(this);
+	origCursor = getCursor();
+	addMouseListener(new MouseListener() {
+	    public void mouseClicked(MouseEvent e) {
+	    }
+
+	    public void mouseEntered(MouseEvent e) {
+		setCursor(handCursor);
+	    }
+
+	    public void mouseExited(MouseEvent e) {
+		setCursor(origCursor);
+	    }
+
+	    public void mousePressed(MouseEvent e) {
+	    }
+
+	    public void mouseReleased(MouseEvent e) {
+	    }
+	});
+    }
+
+    /**
+     * Sets data optained from the View
+     */
+    public void setViewData(View v) {
+	myView = v;
+	doc = (HTMLDocument) myView.getDocument();
+	base = doc.getBase();
+
+	// Set the current font information in the local text attributes
+	Font font = getFont();
+	textAttribs = new SimpleAttributeSet();
+	textAttribs.removeAttribute(StyleConstants.FontSize);
+	textAttribs.removeAttribute(StyleConstants.Bold);
+	textAttribs.removeAttribute(StyleConstants.Italic);
+	textAttribs.addAttribute(StyleConstants.FontFamily,
+				 font.getName());
+	textAttribs.addAttribute(StyleConstants.FontSize,
+				 new Integer(font.getSize()));
+	textAttribs.addAttribute(StyleConstants.Bold,
+				 new Boolean(font.isBold()));
+	textAttribs.addAttribute(StyleConstants.Italic,
+				 new Boolean(font.isItalic()));
+
+
+	// Loop through and find the JHelpContentViewer
+	Component c = container = (Component) myView.getContainer();
+	while (c != null) {
+	    if (c instanceof JHelpContentViewer) {
+		break;
+	    }
+	    c = c.getParent();
+	}
+
+	// Get the helpset if there was JHelpContentViewer
+	if (c !=null) {
+	    TextHelpModel thm = ((JHelpContentViewer)c).getModel();
+	    if (thm != null) {
+		hs = thm.getHelpSet();
+	    }
+	}
+    }
+
+    /**
+     *  properties
+     */
+    private int viewerHeight = 0;
+    private int viewerWidth = 0;
+    private int viewerX = 0;
+    private int viewerY = 0;
+    private String viewerName = "";
+    private int viewerActivator = 0;
+    private int viewerStyle = 0;
+    private Icon viewerIcon;
+    private String content = "";
+    private Map.ID ident;
+
+    /**
+     * Set the content for the secondary viewer
+     * @param content a valid URL
+     */
+    public void setContent(String content) {
+	debug ("setContent");
+	this.content = content;
+	ident = null;
+    }
+
+    /**
+     * Returns the content of the secondary viewer
+     */
+    public String getContent() {
+
+	// return the URL of the ident if set
+	if (ident != null) {
+	    Map map = hs.getCombinedMap();
+	    try {
+	    URL url = map.getURLFromID(ident);
+	    return (url.toExternalForm());
+	    } catch (Exception ex) {
+	    }
+	}
+
+	// just return the content even if ""
+	return content;
+    }
+
+    /**
+     * Set the ID for content in the secondary viewer
+     * @param content a valid URL
+     */
+    public void setId(String id) {
+	debug ("setID");
+	ident = Map.ID.create(id, hs);
+	content = "";
+    }
+
+    /**
+     * Returns the ID of the secondary viewer
+     */
+    public String getId() {
+	return ident.id;
+    }
+
+    /**
+     * Sets the viewer name to display the content in.
+     * Viewer is only valid for ViewerStyle "SecondaryWindow"
+     */
+    public void setViewerName(String name) {
+	debug("setViewerName");
+	viewerName = name;
+    }
+
+    /**
+     * Returns the viewer name
+     */
+    public String getViewerName() {
+	return viewerName;
+    }
+
+    /**
+     * Sets the viewer activator.
+     * Valid activators are
+     * <ul>
+     * <li>javax.help.LinkButton
+     * <li>javax.help.LinkLabel
+     * </ul>
+     * The new activatory type will be used the next time a view is displayed.
+     */
+    public void setViewerActivator(String activator) {
+	debug ("setViewerActivator");
+	if (activator.compareTo(LINK_BUTTON) == 0 &&
+	    viewerActivator != 0) {
+	    viewerActivator = 0;
+	    createLinkButton();
+	} else if (activator.compareTo(LINK_LABEL) == 0 &&
+		      viewerActivator != 1) {
+	    viewerActivator = 1;
+	    createLinkLabel();
+	}
+    }
+
+    /**
+     * Returns the viewer activator
+     */
+    public String getViewerActivator() {
+	switch (viewerActivator) {
+	case 0:
+	    return LINK_BUTTON;
+	case 1:
+	    return LINK_LABEL;
+	}
+	return "unknownStyle";
+    }
+
+    /**
+     * Creates a link button. This is just a JButton with default settings.
+     */
+    private void createLinkButton() {
+	LookAndFeel.installBorder(this, buttonPropertyPrefix + "border");
+	setBorderPainted(true);
+	setFocusPainted(true);
+	setAlignmentY(Container.CENTER_ALIGNMENT);
+	setContentAreaFilled(true);
+	setBackground(UIManager.getColor(buttonPropertyPrefix + "background"));
+	if (textAttribs != null && 
+	    textAttribs.isDefined(StyleConstants.Foreground)) {
+	    setForeground((Color)textAttribs.getAttribute(StyleConstants.Foreground));
+	} else {
+	    setForeground(UIManager.getColor(buttonPropertyPrefix + "foreground"));
+	}
+	invalidate();
+    }
+	
+    /**
+     * Creates a link label. A link label is a form of a JButton but without a
+     * button like appearance.
+     */
+    private void createLinkLabel() {
+	setBorder(new EmptyBorder(1,1,1,1));
+	setBorderPainted(false);
+	setFocusPainted(false);
+	setAlignmentY(getPreferredLabelAlignment());
+	setContentAreaFilled(false);
+	setBackground(UIManager.getColor(editorPropertyPrefix + "background"));
+	if (textAttribs != null &&
+	    textAttribs.isDefined(StyleConstants.Foreground)) {
+	    setForeground((Color)textAttribs.getAttribute(StyleConstants.Foreground));
+	} else {
+	    setForeground(Color.blue);
+	}
+	invalidate();
+    }
+
+    /**
+     * Determine the alignment offset so the text is aligned with other views
+     * correctly.
+     */
+    private float getPreferredLabelAlignment() {
+        Icon icon = (Icon)getIcon();
+        String text = getText();
+
+        Font font = getFont();
+        FontMetrics fm = getToolkit().getFontMetrics(font);
+          
+        Rectangle iconR = new Rectangle();
+        Rectangle textR = new Rectangle();
+        Rectangle viewR = new Rectangle(Short.MAX_VALUE, Short.MAX_VALUE);
+
+        SwingUtilities.layoutCompoundLabel(
+            this, fm, text, icon,
+            getVerticalAlignment(), getHorizontalAlignment(),
+            getVerticalTextPosition(), getHorizontalTextPosition(),
+            viewR, iconR, textR,
+	    (text == null ? 0 : ((BasicButtonUI)ui).getDefaultTextIconGap(this))
+        );
+
+        /* The preferred size of the button is the size of 
+         * the text and icon rectangles plus the buttons insets.
+         */
+        Rectangle r = iconR.union(textR);
+
+        Insets insets = getInsets();
+        r.height += insets.top + insets.bottom;
+
+        /* Ensure that the height of the button is odd,
+         * to allow for the focus line.
+         */
+        if(r.height % 2 == 0) { 
+	    r.height += 1;
+	}
+
+	float offAmt = fm.getMaxAscent() + insets.top;
+	return offAmt/(float)r.height;
+    }
+	
+    /**
+     * Sets the viewer style. There are two valid viewer styles:
+     * <ul>
+     * <li>javax.help.SecondaryWindow
+     * <li>javax.help.Popup
+     * <ul>
+     * <p>
+     * Viewer style is updated the next time the viewer is made visible
+     * @param style a valid ViewerStyle
+     */
+    public void setViewerStyle(String style) {
+	debug ("setViewerStyle");
+	if (style.compareTo(SECONDARY_WINDOW) == 0) {
+	    viewerStyle = 0;
+	} else if (style.compareTo(POPUP) == 0) {
+	    viewerStyle = 1;
+	}
+    }
+
+    /**
+     * Returns the current ViewerStyle
+     */
+    public String getViewerStyle() {
+	switch (viewerStyle) {
+	case 0:
+	    return SECONDARY_WINDOW;
+	case 1:
+	    return POPUP;
+	}
+	return "unknownStyle";
+    }
+
+    /**
+     * Sets the viewer's location to display the content in.
+     * Location is relative to the screen or a modal dialog box
+     * The String must be in the form of "x,y". If no viewer location
+     * is established the default is 0,0 for secondary windows. Location
+     * is ignored for popups.
+     * @see getViewerLocation
+     */
+    public void setViewerLocation(String location) {
+	debug("setViewerLocation");
+	int comma = location.indexOf(",");
+	if (comma != -1) {
+	    String x = location.substring(0,comma).trim();
+	    String y = location.substring(comma+1).trim();
+	    if (x != null && y != null) {
+		viewerX = Integer.parseInt(x);
+		viewerY = Integer.parseInt(y);
+	    }
+	}
+    }
+
+    /**
+     * Returns the viewer Location. Location is relative to the screen or
+     * a modal dialog box. The form of the location is "x,y". 
+     * The default location is 0,0.
+     * @see setViewerLocation
+     */
+    public String getViewerLocation() {
+	String retval = Integer.toString(viewerX) + "," +
+	    Integer.toString(viewerY);
+
+	// try to return the acutal viewer locations if it exists
+	switch (viewerStyle) {
+	case 0:
+	    SecondaryWindow sw =
+		SecondaryWindow.getPresentation(viewerName);
+	    if (sw != null) {
+		Point p = sw.getLocation();
+		if (p != null) {
+		    retval = Integer.toString(p.x) + "," + 
+			Integer.toString(p.y);
+		}
+	    }
+	    break;
+	case 1:
+	    // ignored in popups
+	    break;
+	}
+	return retval;
+    }
+
+    /**
+     * Sets the viewer's size to display the content in.
+     * The String must be in the form of "width,heigt". 
+     * If no size is set the default is 200,200.
+     * @see getViewerSize
+     */
+    public void setViewerSize(String size) {
+	debug ("setViewerSize");
+	int comma = size.indexOf(",");
+	if (comma != -1) {
+	    String width = size.substring(0,comma).trim();
+	    String height = size.substring(comma+1).trim();
+	    if (width != null && height != null) {
+		viewerWidth = Integer.parseInt(width);
+		viewerHeight = Integer.parseInt(height);
+	    }
+	}
+    }
+
+    /**
+     * Returns the viewer's Size. 
+     * The form of the size is "width,height". 
+     * @see setViewerSize
+     */
+    public String getViewerSize() {
+	
+	String retval = "";
+	if (viewerWidth != 0) {
+	    retval = Integer.toString(viewerWidth) + "," +
+		Integer.toString(viewerHeight);
+	}
+
+	// try to return the acutal viewer locations if it exists
+	switch (viewerStyle) {
+	case 0:
+	    SecondaryWindow sw =
+		SecondaryWindow.getPresentation(viewerName);
+	    if (sw != null) {
+		Dimension size = sw.getSize();
+		if (size != null) {
+		    retval = Integer.toString(size.width) + "," +
+			Integer.toString(size.height);
+		}
+	    }
+	    break;
+	case 1:
+	    // nothing for popups
+	    break;
+	}
+	return retval;
+    }
+
+    /**
+     * Sets the icon in the activator by url or id. The url is relative to the
+     * base address of the document.
+     * @see getIcon
+     */
+    public void setIconByName(String name) {
+	debug ("setIconByName");
+	ImageIcon ig = null;
+	URL url=null;
+	// try to get it from the base address
+	try {
+	    url = new URL (base, name); 
+	} catch (java.net.MalformedURLException ex1) {
+	    return;
+	}
+
+	// Valid URLs try the Icon
+	ig = new ImageIcon(url);
+	if (ig != null) {
+	    setIcon(ig);
+	    // if the text is the default text then make it blank
+	    String text = getText();
+	    if (text.compareTo(">") == 0) {
+		setText("");
+	    }
+	}
+    }
+
+    /**
+     * Sets the icon in the activator by id. 
+     * @see getIcon
+     */
+    public void setIconByID(String name) {
+	debug ("setIconByID");
+	ImageIcon ig = null;
+	URL url=null;
+
+	Map map = hs.getCombinedMap();
+	try {
+	    url = map.getURLFromID(ID.create(name, hs)); 
+	} catch (java.net.MalformedURLException e2) {
+	    return;
+	}
+
+	// Valid URLs try the Icon
+	ig = new ImageIcon(url);
+	if (ig != null) {
+	    setIcon(ig);
+	    // if the text is the default text then make it blank
+	    String text = getText();
+	    if (text.compareTo(">") == 0) {
+		setText("");
+	    }
+	}
+    }
+
+    /**
+     * Sets the text Font family for the activator text.
+     * For JDK 1.1 this must a family name of Dialog, DialogInput, Monospaced, 
+     * Serif, SansSerif, or Symbol.
+     */
+    public void setTextFontFamily(String family) {
+	textAttribs.removeAttribute(StyleConstants.FontFamily);
+	textAttribs.addAttribute(StyleConstants.FontFamily, family);
+	setFont(getAttributeSetFont(textAttribs));
+	Font font = getFont();
+    }
+
+    /**
+     * Returns the text Font family name of the activator text
+     */
+    public String getTextFontFamily() {
+	return StyleConstants.getFontFamily(textAttribs);
+    }
+
+    /**
+     * Sets the text size for the activator text.
+     * The String size is a valid Cascading Style Sheet value for
+     * text size. Acceptable values are as follows:
+     * <ul>
+     * <li>xx-small
+     * <li>x-small
+     * <li>small
+     * <li>medium
+     * <li>large
+     * <li>x-large
+     * <li>xx-large
+     * <li>bigger - increase the current base font size by 1
+     * <li>smaller - decrease the current base font size by 1
+     * <li>xxpt - set the font size to a specific pt value of "xx"
+     * <li>+x - increase the current base font size by a value of "x"
+     * <li>-x - decrease the current base font size by a value of "x"
+     * <li>x - set the font size to the point size associated with 
+     * the index "x"
+     * </ul>
+     */
+    public void setTextFontSize(String size) {
+	int newsize, tmp;
+	StyleSheet css = doc.getStyleSheet();
+	try {
+	    if (size.equals("xx-small")) {
+		newsize = (int)css.getPointSize(0);
+	    } else if (size.equals("x-small")) {
+		newsize = (int)css.getPointSize(1);
+	    } else if (size.equals("small")) {
+		newsize = (int)css.getPointSize(2);
+	    } else if (size.equals("medium")) {
+		newsize = (int)css.getPointSize(3);
+	    } else if (size.equals("large")) {
+		newsize = (int)css.getPointSize(4);
+	    } else if (size.equals("x-large")) {
+		newsize = (int)css.getPointSize(5);
+	    } else if (size.equals("xx-large")) {
+		newsize = (int)css.getPointSize(6);
+	    } else if (size.equals("bigger")) {
+		newsize = (int)css.getPointSize("+1");
+	    } else if (size.equals("smaller")) {
+		newsize = (int)css.getPointSize("-1");
+	    } else if (size.endsWith("pt")) {
+		String sz = size.substring(0, size.length() - 2);
+		newsize = Integer.parseInt(sz);
+	    } else {
+		newsize = (int) css.getPointSize(size);
+	    }
+	} catch (NumberFormatException nfe) {
+	    return;
+	}
+	if (newsize == 0) {
+	    return;
+	}
+	textAttribs.removeAttribute(StyleConstants.FontSize);
+	textAttribs.addAttribute(StyleConstants.FontSize,
+				 new Integer(newsize));
+	setFont(getAttributeSetFont(textAttribs));
+	Font font = getFont();
+    }
+
+    /**
+     * Returns the text Font family name of the activator text
+     */
+    public String getTextFontSize() {
+	return Integer.toString(StyleConstants.getFontSize(textAttribs));
+    }
+
+    /**
+     * Sets the text Font Weigth for the activator text.
+     * Valid weights are
+     * <ul>
+     * <li>plain
+     * <li>bold
+     * </ul>
+     */
+    public void setTextFontWeight(String weight) {
+	boolean isBold=false;
+	if (weight.compareTo("bold") == 0) {
+	    isBold = true;
+	} else {
+	    isBold = false;
+	}
+	textAttribs.removeAttribute(StyleConstants.Bold);
+	textAttribs.addAttribute(StyleConstants.Bold, new Boolean(isBold));
+	setFont(getAttributeSetFont(textAttribs));
+	Font font = getFont();
+    }
+
+    /**
+     * Returns the text Font weight of the activator text
+     */
+    public String getTextFontWeight() {
+	if (StyleConstants.isBold(textAttribs)) {
+	    return "bold";
+	}
+	return "plain";
+    }
+
+    /**
+     * Sets the text Font Style for the activator text.
+     * Valid font styles are
+     * <ul>
+     * <li>plain
+     * <li>italic
+     * </ul>
+     */
+    public void setTextFontStyle(String style) {
+	boolean isItalic=false;
+	if (style.compareTo("italic") == 0) {
+	    isItalic = true;
+	} else {
+	    isItalic = false;
+	}
+	textAttribs.removeAttribute(StyleConstants.Italic);
+	textAttribs.addAttribute(StyleConstants.Italic, new Boolean(isItalic));
+	setFont(getAttributeSetFont(textAttribs));
+	Font font = getFont();
+    }
+
+    /**
+     * Returns the text Font style of the activator text
+     */
+    public String getTextFontStyle() {
+	if (StyleConstants.isItalic(textAttribs)) {
+	    return "italic";
+	}
+	return "plain";
+    }
+
+    /**
+     * Sets the text Color for the activator text.
+     * The following is a list of supported Color names
+     * <ul>
+     * <li>black
+     * <li>blue
+     * <li>cyan
+     * <li>darkGray
+     * <li>gray
+     * <li>green
+     * <li>lightGray
+     * <li>magenta
+     * <li>orange
+     * <li>pink
+     * <li>red
+     * <li>white
+     * <li>yellow
+     * </ul>
+     */
+    public void setTextColor(String name) {
+	Color color=null;
+	if (name.compareTo("black") == 0) {
+	    color = Color.black;
+	} else if (name.compareTo("blue") == 0) {
+	    color = Color.blue;
+	} else if (name.compareTo("cyan") == 0) {
+	    color = Color.cyan;
+	} else if (name.compareTo("darkGray") == 0) {
+	    color = Color.darkGray;
+	} else if (name.compareTo("gray") == 0) {
+	    color = Color.gray;
+	} else if (name.compareTo("green") == 0) {
+	    color = Color.green;
+	} else if (name.compareTo("lightGray") == 0) {
+	    color = Color.lightGray;
+	} else if (name.compareTo("magenta") == 0) {
+	    color = Color.magenta;
+	} else if (name.compareTo("orange") == 0) {
+	    color = Color.orange;
+	} else if (name.compareTo("pink") == 0) {
+	    color = Color.pink;
+	} else if (name.compareTo("red") == 0) {
+	    color = Color.red;
+	} else if (name.compareTo("white") == 0) {
+	    color = Color.white;
+	} else if (name.compareTo("yellow") == 0) {
+	    color = Color.yellow;
+	}
+
+	if (color == null) {
+	    return;
+	}
+	textAttribs.removeAttribute(StyleConstants.Foreground);
+	textAttribs.addAttribute(StyleConstants.Foreground, color);
+	setForeground(color);
+    }
+
+    /**
+     * Returns the text Color of the activator text
+     */
+    public String getTextColor() {
+	Color color = getForeground();
+	return color.toString();
+    }
+
+    /**
+     * Gets the font from an attribute set.  This is
+     * implemented to try and fetch a cached font
+     * for the given AttributeSet, and if that fails 
+     * the font features are resolved and the
+     * font is fetched from the low-level font cache.
+     * Font's are cached in the StyleSheet of a document
+     *
+     * @param attr the attribute set
+     * @return the font
+     */
+    private Font getAttributeSetFont(AttributeSet attr) {
+        // PENDING(prinz) add cache behavior
+        int style = Font.PLAIN;
+        if (StyleConstants.isBold(attr)) {
+            style |= Font.BOLD;
+        }
+        if (StyleConstants.isItalic(attr)) {
+            style |= Font.ITALIC;
+        }
+        String family = StyleConstants.getFontFamily(attr);
+        int size = StyleConstants.getFontSize(attr);
+
+	/**
+	 * if either superscript or subscript is
+	 * is set, we need to reduce the font size
+	 * by 2.
+	 */
+	if (StyleConstants.isSuperscript(attr) ||
+	    StyleConstants.isSubscript(attr)) {
+	    size -= 2;
+	}
+
+	// fonts are cached in the StyleSheet so use that
+        return doc.getStyleSheet().getFont(family, style, size);
+    }
+
+    /**
+     * Displays the viewer according to the viewerType
+     */
+    public void actionPerformed(ActionEvent e) {
+	debug ("actionPerformed");
+
+	//	System.err.println("clicked on me...");
+	switch (viewerStyle) {
+	case 0:
+	    if (hs != null) {
+		SecondaryWindow sw = (SecondaryWindow)
+		    SecondaryWindow.getPresentation(hs, viewerName);
+
+		// set the topic to be displayed
+		if (ident != null) {
+		    debug ("ident=" + ident);
+		    try {
+			sw.setCurrentID(ident);
+		    } catch (Exception ex) {
+			debug ("error setting CurrentID");
+			// do nothing
+		    }
+		} else if (content != null) {
+		    debug ("content=" + content);
+		    try {
+			URL url = new URL(base, content);
+			sw.setCurrentURL(url);
+		    } catch (Exception ex) {
+			debug ("error setting URL");
+		    }
+		}
+
+		// set the location if defined
+		if (viewerX != -1) {
+		    sw.setLocation(new Point(viewerX, viewerY));
+		}
+
+		// set the size if desired
+		if (viewerWidth != 0) {
+		    sw.setSize(new Dimension(viewerWidth, viewerHeight)); 
+		}
+
+		// make sure the secondary window is displayed
+		sw.setDisplayed(true);
+
+	    }
+	    break;
+	case 1:
+	    if (hs != null) {
+		Popup popup = (Popup) Popup.getPresentation(hs, viewerName);
+
+		// set the topic to be displayed
+		if (ident != null) {
+		    debug ("ident=" + ident);
+		    try {
+			popup.setCurrentID(ident);
+		    } catch (Exception ex) {
+			debug ("error setting CurrentID");
+			// do nothing
+		    }
+		} else if (content != null) {
+		    debug ("content=" + content);
+		    try {
+			URL url = new URL(base, content);
+			popup.setCurrentURL(url);
+		    } catch (Exception ex) {
+			debug ("error setting URL");
+		    }
+		}
+
+		// set the size if desired
+		if (viewerWidth != 0) {
+		    popup.setSize(new Dimension(viewerWidth, viewerHeight)); 
+		}
+		
+		popup.setInvoker(this);
+
+		// make sure the popup is displayed
+		popup.setDisplayed(true);
+	    }
+	    break;
+	default:
+	    System.out.println ("Unknown viewerStyle");
+	}
+    }
+
+    /**
+     * For printf debugging.
+     */
+    private final static boolean debug = false;
+    private static void debug(String str) {
+        if (debug) {
+            System.out.println("JHSecondaryWindow: " + str);
+        }
+    }
+}
diff --git a/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/JHSecondaryViewerBeanInfo.java b/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/JHSecondaryViewerBeanInfo.java
new file mode 100644
index 0000000000000000000000000000000000000000..634c549981ed1a28dc07db22c3f67240ce6a3963
--- /dev/null
+++ b/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/JHSecondaryViewerBeanInfo.java
@@ -0,0 +1,67 @@
+/*
+ * @(#)JHSecondaryViewerBeanInfo.java	1.7 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.java.help.impl;
+import java.beans.*;
+
+/**
+ * This class provides information about getter/setter methods within 
+ * JHSecondaryWindow. It is usefull for reflection.
+ * @see JHSecondaryViewer
+ *
+ * @author Roger D. Brinkley
+ * @version	1.7	10/30/06
+ */
+public class JHSecondaryViewerBeanInfo extends SimpleBeanInfo {
+
+    public JHSecondaryViewerBeanInfo() {
+    }
+    
+    public PropertyDescriptor[] getPropertyDescriptors() {
+	PropertyDescriptor back[] = new PropertyDescriptor[15];
+	try {
+	    back[0] = new PropertyDescriptor("content", JHSecondaryViewer.class);
+	    back[1] = new PropertyDescriptor("id", JHSecondaryViewer.class);
+	    back[2] = new PropertyDescriptor("viewerName", JHSecondaryViewer.class);
+	    back[3] = new PropertyDescriptor("viewerActivator", JHSecondaryViewer.class);
+	    back[4] = new PropertyDescriptor("viewerStyle", JHSecondaryViewer.class);
+	    back[5] = new PropertyDescriptor("viewerLocation", JHSecondaryViewer.class);
+	    back[6] = new PropertyDescriptor("viewerSize", JHSecondaryViewer.class);
+	    back[7] = new PropertyDescriptor("iconByName", JHSecondaryViewer.class);
+	    back[8] = new PropertyDescriptor("iconByID", JHSecondaryViewer.class);
+	    back[9] = new PropertyDescriptor("text", JHSecondaryViewer.class);
+	    back[10] = new PropertyDescriptor("textFontFamily", JHSecondaryViewer.class);
+	    back[11] = new PropertyDescriptor("textFontSize", JHSecondaryViewer.class);
+	    back[12] = new PropertyDescriptor("textFontWeight", JHSecondaryViewer.class);
+	    back[13] = new PropertyDescriptor("textFontStyle", JHSecondaryViewer.class);
+	    back[14] = new PropertyDescriptor("textColor", JHSecondaryViewer.class);
+	    return back;
+	} catch (Exception ex) {
+	    return null;
+	}
+    }
+}
diff --git a/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/JHelpPrintHandler.java b/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/JHelpPrintHandler.java
new file mode 100644
index 0000000000000000000000000000000000000000..788eb1df0dce6129e44d66cc39bf0db76c396fa2
--- /dev/null
+++ b/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/JHelpPrintHandler.java
@@ -0,0 +1,1058 @@
+/*
+ * @(#)JHelpPrintHandler.java	1.30 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.java.help.impl;
+
+import javax.help.*;
+import javax.help.event.*;
+import java.awt.*;
+import java.awt.event.*;
+import java.awt.geom.*;
+import java.awt.print.*;
+import javax.swing.*;
+import javax.swing.text.*;
+import javax.swing.event.*;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.net.URL;
+import java.net.MalformedURLException;
+import java.util.Vector;
+import java.util.WeakHashMap;
+
+/**
+ * Print handler for JavaHelp. Because JDK1.1 is not supported since JavaHelp
+ * version 2.0 this class contains all printing code.
+ *
+ * @author Roger D. Brinkley
+ * @author Stepan Marek
+ * @version   1.30     10/30/06
+ */
+public class JHelpPrintHandler implements ActionListener {
+    
+    public static final String PRINT_BUTTON_NAME = "PrintButton";
+    public static final String PAGE_SETUP_BUTTON_NAME = "PageSetupButton";
+    public static final String PRINT_LATER_BUTTON_NAME = "PrintLaterButton";
+    
+    /**
+     * Specifies whether action is enabled; the default is true.
+     */
+    private boolean enabled = true;
+    private PrinterJob printerJob;
+    private PageFormat pageFormat;
+    private JHelp help;
+    private HelpModel helpModel;
+    // private DefaultListModel listModel = new DefaultListModel();
+    private URL documentURL;
+    private String documentTitle;
+    
+    
+    
+    public JHelpPrintHandler(JHelp help) {
+        this.help = help;
+    }
+    
+    private static WeakHashMap handlers;
+    
+    public static JHelpPrintHandler getJHelpPrintHandler(JHelp help) {
+        JHelpPrintHandler handler = null;
+        if (handlers == null) {
+            handlers = new WeakHashMap();
+        } else {
+            handler = (JHelpPrintHandler)handlers.get(help);
+        }
+        if (handler == null) {
+            handler = new JHelpPrintHandler(help);
+            handlers.put(help, handler);
+        }
+        return handler;
+    }
+
+    /**
+     * If any <code>PropertyChangeListeners</code> have been registered, the
+     * <code>changeSupport</code> field describes them.
+     */
+    protected SwingPropertyChangeSupport changeSupport;
+    
+    /**
+     * Supports reporting bound property changes.  This method can be called
+     * when a bound property has changed and it will send the appropriate
+     * <code>PropertyChangeEvent</code> to any registered
+     * <code>PropertyChangeListeners</code>.
+     */
+    protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) {
+        if (changeSupport == null) {
+            return;
+        }
+        changeSupport.firePropertyChange(propertyName, oldValue, newValue);
+    }
+    
+    
+    /**
+     * Adds a <code>PropertyChangeListener</code> to the listener list.
+     * The listener is registered for all properties.
+     * <p>
+     * A <code>PropertyChangeEvent</code> will get fired in response to setting
+     * a bound property, e.g. <code>setFont</code>, <code>setBackground</code>,
+     * or <code>setForeground</code>.
+     * Note that if the current component is inheriting its foreground,
+     * background, or font from its container, then no event will be
+     * fired in response to a change in the inherited property.
+     *
+     * @param listener  The <code>PropertyChangeListener</code> to be added
+     *
+     * @see Action#addPropertyChangeListener
+     */
+    public synchronized void addPropertyChangeListener(PropertyChangeListener listener) {
+        if (changeSupport == null) {
+            changeSupport = new SwingPropertyChangeSupport(this);
+        }
+        changeSupport.addPropertyChangeListener(listener);
+    }
+    
+    
+    /**
+     * Removes a <code>PropertyChangeListener</code> from the listener list.
+     * This removes a <code>PropertyChangeListener</code> that was registered
+     * for all properties.
+     *
+     * @param listener  the <code>PropertyChangeListener</code> to be removed
+     *
+     * @see Action#removePropertyChangeListener
+     */
+    public synchronized void removePropertyChangeListener(PropertyChangeListener listener) {
+        if (changeSupport == null) {
+            return;
+        }
+        changeSupport.removePropertyChangeListener(listener);
+    }
+    
+    /**
+     * Returns true if the action is enabled.
+     *
+     * @return true if the action is enabled, false otherwise
+     * @see Action#isEnabled
+     */
+    public boolean isEnabled() {
+        return enabled;
+    }
+    
+    /**
+     * Enables or disables the action.
+     *
+     * @param newValue  true to enable the action, false to
+     *                  disable it
+     * @see Action#setEnabled
+     */
+    public void setEnabled(boolean newValue) {
+        boolean oldValue = this.enabled;
+        this.enabled = newValue;
+        firePropertyChange("enabled", new Boolean(oldValue), new Boolean(newValue));
+    }
+    
+    /**
+     * ActionListener to perform printing. The current implementation of Swing
+     * requires that this go through an ActionListener as it must be in the
+     * EventDispatchThread.
+     */
+    public void actionPerformed(ActionEvent e) {
+        
+        String name = null;
+        Object source = e.getSource();
+        if (source instanceof MenuComponent) {
+            name = ((MenuComponent)source).getName();
+        } if (source instanceof Component) {
+            name = ((Component)source).getName();
+        }
+        
+        if (isEnabled()) {
+            if (name != null && name.equals(JHelpPrintHandler.PAGE_SETUP_BUTTON_NAME)) {
+                printSetup();
+            } else {
+                if (getHelp() != null) {
+                    print(getURLs());
+                } else if (getHelpModel() != null) {
+                    print(getHelpModel().getCurrentURL());
+                }
+            }
+        }
+    }
+    
+    
+    public void printSetup() {
+        if (isEnabled()) {
+            new PageSetupThread().start();
+        }
+    }
+    
+    public void print(URL url) {
+        if (isEnabled()) {
+            new PrintThread(url).start();
+        }
+    }
+    
+    public void print(URL[] urls) {
+        if (isEnabled()) {
+            new PrintThread(urls).start();
+        }
+    }
+    
+    private JHelp getHelp() {
+        return help;
+    }
+    
+    private URL[] getURLs() {
+        URL[] urls = null;
+        if (getHelp() != null) {
+            TreeItem[] items = getHelp().getSelectedItems();
+            if (items != null) {
+                debug("pages to print: "+items.length);
+                urls = new URL[items.length];
+                for (int i = 0; i < items.length; i++) {
+                    debug("   "+items[i].getName()+": "+items[i].getURL());
+                    urls[i] = items[i].getURL();
+                }
+            }
+        }
+        return urls;
+    }
+    
+    /** Getter for property pageFormat.
+     * @return Value of property pageFormat.
+     */
+    public PageFormat getPageFormat() {
+        if ((pageFormat == null) && (getPrinterJob() != null)) {
+            pageFormat = getPrinterJob().defaultPage();
+        }
+        return pageFormat;
+    }
+    
+    /**
+     * @deprecated As of JavaHelp version 2.0,
+     * replaced by <code>getPageFormat()</code>.
+     */
+    public PageFormat getPF() {
+        return getPageFormat();
+    }
+    
+    /** Setter for property pageFormat.
+     * @param pageFormat New value of property pageFormat.
+     */
+    public void setPageFormat(PageFormat pageFormat) {
+        if (this.pageFormat == pageFormat) return;
+        PageFormat oldPageFormat = this.pageFormat;
+        this.pageFormat = pageFormat;
+        firePropertyChange("pageFormat", oldPageFormat, pageFormat);
+    }
+    
+    /**
+     * @deprecated As of JDK version 2.0,
+     * replaced by <code>setPageFormat(pageFormat)</code>.
+     */
+    public void setPF(PageFormat pf) {
+        setPageFormat(pf);
+    }
+    
+    public PrinterJob getPrinterJob() {
+        if (printerJob == null) {
+            try {
+                printerJob = PrinterJob.getPrinterJob();
+            } catch (SecurityException se) {
+                setEnabled(false);
+                processException(se);
+            }
+        }
+        return printerJob;
+    }
+    
+    /**
+     * Sets the PrintHandler to handle pageSetup as a separate action from
+     * printing. PageSetup is only in 1.2 but we put in the 1.1 code to make
+     * it easier. On 1.1 this will essential do nothing. On 1.2 this sets up
+     * the button so we know if we're printing or just doing a page setup.
+     */
+    public void handlePageSetup(Component psComp) {
+        psComp.setName(JHelpPrintHandler.PAGE_SETUP_BUTTON_NAME);
+    }
+    
+    public void setHelpModel(HelpModel helpModel) {
+        HelpModel oldModel = this.helpModel;
+        this.helpModel = helpModel;
+        firePropertyChange("helpModel", oldModel, helpModel);
+    }
+    
+    /** Getter for property model.
+     * @return Value of property model.
+     */
+    public HelpModel getHelpModel() {
+        return helpModel;
+    }
+    
+    /**
+     * Returns the specified component's toplevel <code>Frame</code> or
+     * <code>Dialog</code>.
+     *
+     * @param comp the <code>Component</code> or <code>MenuComponent</code> to
+     *          check for a <code>Frame</code> or <code>Dialog</code>
+     * @return the <code>Frame</code> or <code>Dialog</code> that
+     *		contains the <code>Component</code> or <code>MenuComponent</code>,
+     *          or <code>null</code>, if there is not a valid
+     *         	<code>Frame</code> or <code>Dialog</code> parent
+     */
+    static Window getWindowForObject(Object comp) {
+        if (comp == null || comp instanceof Frame || comp instanceof Dialog) {
+            return (Window)comp;
+        }
+        Object parent = null;
+        if  (comp instanceof MenuComponent) {
+            parent = ((MenuComponent)comp).getParent();
+        } else if (comp instanceof Component) {
+            parent = ((Component)comp).getParent();
+        }
+        return getWindowForObject(parent);
+    }
+    
+    static Insets getInsetsForContainer(Container c) {
+        Insets i = c.getInsets();
+        for (c = c.getParent(); c != null; c = c.getParent()) {
+            Insets ii = c.getInsets();
+            i.bottom += ii.bottom;
+            i.left   += ii.left;
+            i.right  += ii.right;
+            i.top    += ii.top;
+            if (c instanceof Window) {
+                break;
+            }
+        }
+        return i;
+    }
+    
+    /**
+     * Create a handler for the given type from HelpSet or from the
+     * default registry of editor kits.
+     *
+     * @param type the content type
+     * @return the editor kit, or null if there is nothing
+     *   registered for the given type.
+     */
+    EditorKit createEditorKitForContentType(String type) {
+        
+        HelpModel model = null;
+        JHelp help = getHelp();
+        
+        if (help != null) {
+            model = help.getModel();
+        } else {
+            model = getHelpModel();
+        }
+        
+        if (model == null) {
+            return null;
+        }
+        
+        HelpSet hs = model.getHelpSet();
+        if (hs == null) {
+            return null;
+        }
+        
+        // try to dynamically load the support
+        String classname = (String) hs.getKeyData(HelpSet.kitTypeRegistry, type);
+        // I don't know of a class for this type
+        if (classname == null) {
+            return null;
+        }
+        
+        ClassLoader loader = (ClassLoader) hs.getKeyData(HelpSet.kitLoaderRegistry, type);
+        if (loader == null) {
+            loader = hs.getLoader();
+        }
+        
+        EditorKit k = null;
+        try {
+            Class c;
+            if (loader != null) {
+                c = loader.loadClass(classname);
+            } else {
+                c = Class.forName(classname);
+            }
+            k = (EditorKit) c.newInstance();
+            // kitRegistry.put(type, k);
+        } catch (Throwable e) {
+            System.err.println(e);
+            k = null;
+        }
+        
+        // create a copy of the prototype or null if there
+        // is no prototype.
+        if (k != null) {
+            return (EditorKit) k.clone();
+        }
+        return k;
+    }
+    
+    class PageSetupThread extends Thread {
+        
+        PrinterJob job;
+        
+        PageSetupThread() {
+            setDaemon(true);
+        }
+        
+        public void run() {
+            PrinterJob job = getPrinterJob();
+            if (job != null) {
+                synchronized (job) {
+                    try {
+                        setPageFormat(job.pageDialog(getPageFormat()));
+                    } catch (Exception e) {
+                        processException(e);
+                    }
+                }
+            }
+        }
+    }
+    
+    class PrintThread extends Thread {
+        
+        private URL[] urls;
+        private int index = 0;
+        
+        PrintThread(URL url) {
+            this(new URL[] {url});
+        }
+        
+        PrintThread(URL[] urls) {
+            this.urls = urls;
+            setDaemon(true);
+        }
+        
+        public void run() {
+            PrinterJob job = getPrinterJob();
+            if (job != null) {
+                synchronized (job) {
+		    JEditorPane editor = new JHEditorPane();
+		    
+		    JFrame frame = new JHFrame();
+		    frame.setContentPane(editor);
+		    
+		    try {
+			job.setPageable(new JHPageable(editor, urls, 
+						       (PageFormat)JHelpPrintHandler.this.getPageFormat().clone()));
+		    } catch (Exception e) {
+			processException(e);
+		    }
+                        
+                    if (job.printDialog()) {
+                        try {
+                            job.print();
+                        } catch (Exception e) {
+                            processException(e);
+                        }
+                    }
+		    frame.dispose();
+                }
+            }
+        }
+    }
+    
+    class PageTransform extends AffineTransform {
+        
+        /** Holds value of property height. */
+        private double height;
+        
+        /** Getter for property height.
+         * @return Value of property height.
+         */
+        public double getHeight() {
+            return height;
+        }
+        
+        /** Setter for property height.
+         * @param height New value of property height.
+         *
+         * @throws PropertyVetoException
+         */
+        public void setHeight(double height) {
+            this.height = height;
+        }
+        
+    }
+    
+    class JHPrintable implements Printable, PropertyChangeListener {
+        
+        JEditorPane editor;
+        URL url;
+        PageFormat pf;
+        int firstPage;
+        boolean scaleToFit;
+        Vector transforms;
+        
+        public JHPrintable(JEditorPane editor, URL url, PageFormat pf, int firstPage, boolean scaleToFit) {
+            this.editor = editor;
+            this.url = url;
+            this.pf = pf;
+            this.firstPage = firstPage;
+            this.scaleToFit = scaleToFit;
+        }
+        
+        private synchronized void loadPage() {
+            debug("JHPrintable.loadPage(): "+url);
+	    URL currentURL = editor.getPage();
+	    if (currentURL != null && currentURL.equals(url)) {
+		// If the editors have the same url return otherwise
+		// you'll just wait forever since a set page with
+		// the same URL doesn't send a property change notice
+		return;
+	    }
+            editor.addPropertyChangeListener("page", this);
+            try {
+                editor.setPage(url);
+                wait();
+            } catch (Exception e) {
+                processException(e);
+            }
+            editor.removePropertyChangeListener("page", this);
+        }
+        
+        public int getNumberOfPages() {
+            if (transforms == null) {
+                loadPage();
+                transforms = createTransforms();
+            }
+            return transforms.size();
+        }
+        
+        public synchronized void propertyChange(PropertyChangeEvent evt) {
+            notifyAll();
+        }
+        
+        public Vector createTransforms() {
+	    
+	    int page = 0;
+            Vector transforms = new Vector();
+            
+            double curHeight = 0.0, height = 0.0;
+            double yval = 0.0;
+            double scale = 1.0;
+            
+            Component root = SwingUtilities.windowForComponent(editor);
+            if (root == null) {
+                root = editor;
+            }
+            
+            root.addNotify();
+            
+            View rootview = editor.getUI().getRootView(editor);
+            Rectangle viewRec = JHelpPrintHandler.getViewRec(rootview, (float)pf.getImageableWidth(), (float)pf.getImageableHeight());
+            debug("viewRec=" + viewRec);
+            
+            Insets i = JHelpPrintHandler.getInsetsForContainer(editor);
+            root.setBounds(0, 0, viewRec.width + i.left + i.right, viewRec.height + i.top + i.bottom);
+            root.setVisible(true);
+            
+            // Do any scaling that is necessary
+            if (scaleToFit) {
+                if (viewRec.getWidth() > pf.getImageableWidth()) {
+                    scale = pf.getImageableWidth() / viewRec.getWidth();
+                }
+                debug("scale=" + scale
+                + " ImageableWidth=" + pf.getImageableWidth()
+                + " width=" + viewRec.getWidth());
+            }
+            
+            // Determine the print Rectangle size
+            Rectangle2D.Double printRec =
+            new Rectangle2D.Double(0.0, 0.0, pf.getImageableWidth(), pf.getImageableHeight() / scale);
+            debug("printRec=" + printRec);
+            Position.Bias[] bias = new Position.Bias[1];
+            
+            while (true) {
+                debug("preparing page=" + page + " curHeight=" + curHeight);
+                
+                double maxHeight = printRec.getHeight() + curHeight;
+                
+                // Find the point that corresponds to the end of the current
+                // page that we are printing.
+                int point = rootview.viewToModel(0, (float) maxHeight, viewRec, bias);
+                debug("point=" + point);
+                try {
+                    // Get the Rectangle around that point
+                    Shape s = rootview.modelToView(point, viewRec, bias[0]);
+                    Rectangle2D pointRec = s.getBounds2D();
+                    debug("pointRec=" + pointRec);
+                    
+                    // Create a proper offset on the printed page
+                    yval = curHeight;
+                    
+                    // Create the proper height to print.
+                    // Be carefull not chop anything off.
+                    // All print the full view if it will fit, otherwise
+                    // print the point above.
+                    height = pointRec.getY() - 1.0;
+                    debug("Starting height=" + height);
+                    if (maxHeight >= pointRec.getY() + pointRec.getHeight()) {
+                        height = pointRec.getY() + pointRec.getHeight() - 1.0;
+                        debug("Adjusted height=" + height);
+                    }
+                    
+                    // Make sure there isn't any other object that would be slightly
+                    // lower.
+                    double baseY = pointRec.getY();
+                    double baseHeight = pointRec.getY() + pointRec.getHeight() - 1.0;
+                    // move over 20 pixels. We'd user pointRec.getWidth() but it's 0
+                    double nextX = pointRec.getX() + 20.0;
+                    double testY = 0.0, testHeight = 0.0;
+                    Rectangle2D testRec = pointRec;
+                    while (true) {
+                        // don't look past max width.
+                        if (nextX > (pf.getImageableWidth() * scale)) {
+                            break;
+                        }
+                        int point2 =
+                        rootview.viewToModel((float) nextX,
+                        (float) maxHeight,
+                        viewRec, bias);
+                        Shape s2 = rootview.modelToView(point2, viewRec, bias[0]);
+                        Rectangle2D pointRec2 = s2.getBounds2D();
+                        // if this is same Rectangle then try 20 pixels over
+                        if (testRec.equals(pointRec2) || pointRec2.getX() < nextX) {
+                            nextX += 20.0;
+                            continue;
+                        }
+                        debug("pointRec2=" + pointRec2);
+                        testY = pointRec2.getY();
+                        testHeight = pointRec2.getY() + pointRec2.getHeight() - 1.0;
+                        
+                        // if test height is less than base y then don't bother
+                        // testing. Just pass through
+                        if (testHeight > baseY) {
+                            
+                            // if the testHeight is greater than the baseHeight
+                            // we might want to use the test height values
+                            if (testHeight > baseHeight) {
+                                // if the test height is less than the max height
+                                // use that height instead
+                                if (testHeight < maxHeight) {
+                                    height = testHeight;
+                                    baseHeight = testHeight;
+                                    if (testY < baseY) {
+                                        baseY = testY;
+                                    }
+                                    debug("Adjust height to testheight " + height);
+                                } else {
+                                    // the test height is greater than the max
+                                    // height.
+                                    if (testY > baseHeight) {
+                                        // test Y is greater than the base height
+                                        // move the base height to just above
+                                        // test Y
+                                        height = testY - 1.0;
+                                        baseHeight = testHeight;
+                                        baseY = testY;
+                                        debug("new base component " + height);
+                                    } else {
+                                        // test Y is less than base height.
+                                        // if the test Y is less than the base y
+                                        // use it
+                                        if (testY < baseY) {
+                                            height = testY - 1.0;
+                                            baseY = testY;
+                                            baseHeight = testHeight;
+                                            debug("test height > maxheight. Adjust height testY - 1 " + height);
+                                        } else {
+                                            // otherwise use the base y
+                                            height = baseY - 1.0;
+                                            baseHeight = testHeight;
+                                            debug("test height > maxheight. Adjust height baseY - 1 " + height);
+                                        }
+                                    }
+                                }
+                            } else {
+                                // the base height is greater than the test
+                                // height use the base height values
+                                if (baseHeight < maxHeight) {
+                                    // this value has already been set to this
+                                    // height but I'm doing this for consistency
+                                    // The baseHeight is valid so use it.
+                                    height = baseHeight;
+                                    if (testY < baseY) {
+                                        baseY = testY;
+                                    }
+                                    debug("baseHeight ok " + height);
+                                } else {
+                                    // the base height is greater than the max height
+                                    // if the base Y is less than the test y use it
+                                    if (baseY <= testY) {
+                                        height = baseY - 1.0;
+                                        debug("baseHeight too long - height ok" + height);
+                                    } else {
+                                        // otherwise use the test Y
+                                        height = testY - 1.0;
+                                        baseY = testY;
+                                        debug("baseHeight too long - use testY - 1 " + height);
+                                    }
+                                }
+                            }
+                        }
+                        testRec = pointRec2;
+                        // move over 20 pixels. pointRec.width is 0
+                        nextX = testRec.getX() + 20.0;
+                    }
+                    
+                    // Create new transform for each page to be printed
+                    PageTransform t = new PageTransform();
+                    
+                    // Set the translation values so we print the
+                    // correct part of editor componenet.
+                    t.translate(pf.getImageableX(), pf.getImageableY());
+                    debug("t.translate="+t);
+                    t.translate(- (double) i.left * scale, - ((double) i.top + yval) * scale);
+                    debug("t.translate="+t);
+                    
+                    // Scaling will advirsely affect the yval. Multiple yval to scale
+                    // to correct the future scaling.
+                    t.scale(scale, scale);
+                    debug("t.scale="+t);
+                    
+                    // Store height
+                    t.setHeight(height + (double) i.top);
+                    
+		    // bug fix for JDK1.4 which caused repeated pages to be printed
+		    if (curHeight == height + 1.0) {
+			break;
+		    }
+
+                    // Strore transform
+                    transforms.add(page, t);
+                    
+                    // Set the current Height for the next page.
+                    curHeight = height + 1.0;
+                    debug("Setting curHeight=" + curHeight);
+                    
+                    // increment the page counter
+                    page++;
+                    
+                    // If the current Height is greater than the viewRec height
+                    // then we are done.
+		    debug ("curHeight="+curHeight+" viewRec.getHeight()="+ viewRec.getHeight());
+                    if (curHeight >= viewRec.getHeight()) {
+                        break;
+                    }
+                    
+                } catch (BadLocationException ble) {
+                    break;
+                }
+            }
+            return transforms;
+        }
+        
+        private void printHeader(Graphics2D g2d, int pi) {
+            
+            g2d.setClip(new Rectangle2D.Double(0.0, 0.0, pf.getWidth(), pf.getHeight()));
+            g2d.setFont(new Font("Serif", Font.ITALIC, 10));
+            
+            String s = (String)editor.getDocument().getProperty(Document.TitleProperty)
+            + " " + (pi + 1) + "/" +transforms.size();
+            
+            Rectangle2D rec = g2d.getFontMetrics().getStringBounds(s, g2d);
+            g2d.drawString(s, (float)(pf.getWidth() - rec.getX() - rec.getWidth() - 36.0), (float)36.0);
+            g2d.setClip(new Rectangle2D.Double(
+            pf.getImageableX(),
+            pf.getImageableY(),
+            pf.getImageableWidth(),
+            pf.getImageableHeight()
+            ));
+        }
+        
+        public int print(Graphics pg, PageFormat pageFormat, int pi) {
+            
+            debug("Printing document page=" + pi);
+            pi -= firstPage;
+            debug("Printing page=" + pi);
+            
+            if (pi >= getNumberOfPages()) {
+                return Printable.NO_SUCH_PAGE;
+            }
+            
+            Graphics2D g2d = (Graphics2D) pg;
+            
+            printHeader(g2d, pi);
+            
+            // Apply transformation for current page
+            g2d.transform((AffineTransform) transforms.get(pi));
+            debug("Graphics tansform=" + g2d.getTransform());
+            debug("Graphics clip=" + g2d.getClip());
+            
+            // Get the Rectangle of the adjusted print graphics. This helps in
+            // printing the correct height. Indirectly gotten through
+            // the shape to perserve the coordinates (prevent rounding)
+            Rectangle2D g2dRec = g2d.getClip().getBounds2D();
+            
+            // See if any adjustments to the height are necessary
+            // If so create a new Rectangle and apply it to the g2d
+            double height = ((PageTransform)transforms.get(pi)).getHeight();
+            double adjheight = g2dRec.getY() + g2dRec.getHeight() - 1.0 - height;
+            if (adjheight > 0.0) {
+                debug("Graphics adjusted height=" + adjheight);
+                g2d.clip(new Rectangle2D.Double(
+                g2dRec.getX(),
+                g2dRec.getY(),
+                g2dRec.getWidth(),
+                g2dRec.getHeight() - adjheight
+                ));
+                g2dRec = g2d.getClip().getBounds2D();
+                debug("Graphics tansform=" + g2d.getTransform());
+                debug("Graphics clip=" + g2d.getClip());
+            }
+            
+            // Just print editor
+            if (g2dRec.getY() < height) {
+                // using editor.printAll(g2d) here should be better for jdk1.3
+                // but there are bugs in jdk1.2
+                editor.paint(g2d);
+            } else {
+                return Printable.NO_SUCH_PAGE;
+            }
+            
+            return Printable.PAGE_EXISTS;
+        }
+    }
+    
+    class EmptyPrintable implements Printable {
+        public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException {
+            return Printable.NO_SUCH_PAGE;
+        }
+    }
+    
+    public class JHPageable implements Pageable {
+        
+        private JEditorPane editor;
+        private URL[] urls;
+        private PageFormat pf;
+        private int lastIndex = -1;
+        private int lastPage = 0;
+        private Printable printable = new EmptyPrintable();
+	private int numPages = 0;
+        
+        public JHPageable(JEditorPane editor, URL[] urls, PageFormat pf) {
+            this.editor = editor;
+            this.urls = urls;
+            this.pf = pf;
+        }
+        
+        /**
+         * Returns the <code>PageFormat</code> of the page specified by
+         * <code>pageIndex</code>.
+         * @param pageIndex the zero based index of the page whose
+         *           <code>PageFormat</code> is being requested
+         * @return the <code>PageFormat</code> describing the size and
+         * 		orientation.
+         * @exception <code>IndexOutOfBoundsException</code>
+         *         the <code>Pageable</code> does not contain the requested
+         * 		page.
+         */
+        public PageFormat getPageFormat(int pageIndex) throws IndexOutOfBoundsException {
+            return pf;
+        }
+        
+        /**
+         * Returns the number of pages in the set.
+         * To enable advanced printing features,
+         * it is recommended that <code>Pageable</code>
+         * implementations return the true number of pages
+         * rather than the
+         * UNKNOWN_NUMBER_OF_PAGES constant.
+         * @return the number of pages in this <code>Pageable</code>.
+         */
+        public int getNumberOfPages() {
+	    if (numPages != 0) {
+		// only do this once ???
+		return numPages;
+	    }
+	    if (urls != null) {
+		for (int i=0; i < urls.length; i++) {
+		    JHPrintable printable = new JHPrintable(editor, urls[i],
+							  pf, 0, true);
+		    numPages += printable.getNumberOfPages();
+		}
+	    }
+	    return numPages;
+        }
+        
+        /**
+         * Returns the <code>Printable</code> instance responsible for
+         * rendering the page specified by <code>pageIndex</code>.
+         * @param pageIndex the zero based index of the page whose
+         *           <code>Printable</code> is being requested
+         * @return the <code>Printable</code> that renders the page.
+         * @exception <code>IndexOutOfBoundsException</code>
+         *           the <code>Pageable</code> does not contain the requested
+         * 		  page.
+         */
+        public Printable getPrintable(int pageIndex) throws IndexOutOfBoundsException {
+            
+            debug("JHPageable.getPrintable("+pageIndex+"): lastIndex="+lastIndex+", lastPage"+lastPage);
+            
+            if (pageIndex < 0) {
+                throw new IndexOutOfBoundsException(pageIndex + " < 0");
+            }
+            
+            if (urls != null) {
+                while ((pageIndex >= lastPage) && ((lastIndex + 1) < urls.length)) {
+                    if (urls[++lastIndex] != null) {
+                        printable = new JHPrintable(editor, urls[lastIndex], 
+						    pf, lastPage, true);
+                        lastPage += ((JHPrintable)printable).getNumberOfPages();
+                    } else {
+                        printable = new EmptyPrintable();
+                    }
+                }
+            }
+            
+            if (pageIndex > lastPage) {
+                throw new IndexOutOfBoundsException(pageIndex + " > " + lastPage);
+            }
+            
+            return printable;
+        }
+        
+    }
+    
+    /**
+     * Setups size of editor and return its optimal width.
+     */
+    static protected Rectangle getViewRec(View rootview, float width, float height) {
+        Rectangle r = new Rectangle();
+        rootview.setSize(width, height);
+        r.width = (int) Math.max((long)Math.ceil(rootview.getMinimumSpan(View.X_AXIS)), (long) width);
+        r.height = (int) Math.min((long)Math.ceil(rootview.getPreferredSpan(View.Y_AXIS)), (long) Integer.MAX_VALUE);
+        rootview.setSize(r.width, r.height);
+        if (rootview.getView(0) instanceof BoxView) {
+            BoxView box = (BoxView) rootview.getView(0);
+            r.width = box.getWidth();
+            r.height = box.getHeight();
+        } else {
+            r.height = (int) Math.min((long)Math.ceil(rootview.getPreferredSpan(View.Y_AXIS)), (long) Integer.MAX_VALUE);
+        }
+        return r;
+    }
+    
+    /**
+     * Private implementation of invisible Frame which is used
+     * as a parent for JHEditorPane. This Frame has no peer so it cannot
+     * be displayed on screen and visibility is just predended.
+     */
+    class JHFrame extends JFrame {
+        
+        public void addNotify() {
+            getRootPane().addNotify();
+        }
+        
+        public void validate() {
+            validateTree();
+        }
+        
+        // The editor has to have a graphics set for it.
+        // This is bug in jdk1.2.2. The Graphics is not necessery
+        // for jdk1.1 and jdk1.3.
+        public Graphics getGraphics() {
+            return JHelpPrintHandler.this.getHelp().getGraphics();
+        }
+        
+    }
+    
+    /**
+     * Implementation of JEditorPane which support EditorKit created from
+     * current HelpSet. Listeners are not necessery for printing and they are
+     * skiped as workaround of bug in Component.addNotify() method in jdk1.1.
+     */
+    class JHEditorPane extends JEditorPane {
+        
+        public JHEditorPane() {
+            setDoubleBuffered(false);
+            setEditable(false);
+            
+            // turn of DnD support
+            // necessary for jdk1.4
+            setDropTarget(null);
+        }
+        
+        public EditorKit getEditorKitForContentType(String type) {
+            EditorKit k = JHelpPrintHandler.this.createEditorKitForContentType(type);
+            if (k == null) {
+                k = super.getEditorKitForContentType(type);
+            }
+            return k;
+        }
+        
+        // This methods enable to keep references to listeners null. It is
+        // workaround for bug in Component.addNotify() method in jdk1.1
+        // and jdk1.2. Moreover it can save resources.
+        public void addMouseListener(MouseListener l) {
+        }
+        
+        public void removeMouseListener(MouseListener l) {
+        }
+        
+        public void addMouseMotionListener(MouseMotionListener l) {
+        }
+        
+        public void removeMouseMotionListener(MouseMotionListener l) {
+        }
+        
+        public void addFocusListener(FocusListener l) {
+        }
+        
+        public void removeFocusListener(FocusListener l) {
+        }
+        
+        public void addKeyListener(KeyListener l) {
+        }
+        
+        public void removeKeyListener(KeyListener l) {
+        }
+        
+    }
+    
+    protected static void processException(Exception e) {
+        if (debug) {
+            e.printStackTrace();
+        } else {
+            System.err.println(e);
+        }
+    }
+    
+    /**
+     * For printf debugging.
+     */
+    private static final boolean debug = false;
+    private static void debug(String str) {
+        if (debug) {
+            System.err.println("JHelpPrintHandler: " + str);
+        }
+    }
+    
+}
diff --git a/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/JHelpPrintHandler1_2.java b/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/JHelpPrintHandler1_2.java
new file mode 100644
index 0000000000000000000000000000000000000000..fa205a141768b47bec9fa1c1ff4e9581b8de04a4
--- /dev/null
+++ b/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/JHelpPrintHandler1_2.java
@@ -0,0 +1,68 @@
+/*
+ * @(#)JHelpPrintHandler1_2.java	1.12 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.java.help.impl;
+
+import javax.help.JHelp;
+import javax.help.HelpModel;
+import java.awt.Component;
+
+/**
+ * Print handler for JavaHelp. Handles all printer requests for printing
+ * in JDK1.2 and above. Because JDK1.1 is not supported since JavaHelp version 2.0
+ * all code was moved into JHelpPrintHandler. This class is preserved for backward 
+ * compatibility.
+ *
+ * @author Roger D. Brinkley
+ * @author Stepan Marek
+ * @version   1.12     10/30/06
+ */
+
+public class JHelpPrintHandler1_2 extends JHelpPrintHandler {
+
+    public JHelpPrintHandler1_2(JHelp help) {
+        super(help);
+    }    
+
+    /*
+    public JHelpPrintHandler1_2(HelpModel model) {
+        super(model);
+    }
+     */
+    
+    /**
+     * JHelpPrintHandler constructor. Creates a JHelpPrintHandler with a null
+     * Document.
+     * @param model The HelpModel to derive URLs from.
+     * @param comp The component from which the Frame can be optained for 1.1 printing
+     */
+    /*
+    public JHelpPrintHandler1_2(HelpModel model, Component comp) {
+        super (model, comp);
+    }
+     */
+}
diff --git a/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/LangElement.java b/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/LangElement.java
new file mode 100644
index 0000000000000000000000000000000000000000..e7146cf23ffb58d40c5235863aa81d95919685e0
--- /dev/null
+++ b/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/LangElement.java
@@ -0,0 +1,60 @@
+/*
+ * @(#)LangElement.java	1.5 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @(#) LangElement.java 1.5 - last change made 10/30/06
+ */
+package com.sun.java.help.impl;
+
+import java.util.Locale;
+
+/** 
+ * LangElement is a simple little internal class to keep
+ * track of tags and the langs
+ *
+ * @author Roger D. Brinkley
+ * @version 1.5	10/30/06
+ */
+
+public class LangElement {
+
+    Tag tag;
+    Locale locale;
+
+    public LangElement (Tag tag, Locale locale) {
+	this.tag = tag;
+	this.locale = locale;
+    }
+
+    public Tag getTag() {
+	return tag;
+    }
+
+    public Locale getLocale() {
+	return locale; 
+    }
+}
diff --git a/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/Parser.java b/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/Parser.java
new file mode 100644
index 0000000000000000000000000000000000000000..5866b614debc225d68871d28aac3076feee1c850
--- /dev/null
+++ b/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/Parser.java
@@ -0,0 +1,171 @@
+/*
+ * @(#)Parser.java	1.13 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @(#) Parser.java 1.13 - last change made 10/30/06
+ */
+
+package com.sun.java.help.impl;
+
+/**
+ * This class parses an HTML or XML document.
+ *
+ * @author Roger D. Brinkley
+ * @author Eduardo Pelegri-Llopart
+ * @version	1.13	10/30/06
+ */
+import java.util.Vector;
+import java.io.Reader;
+import java.io.InputStream;
+import java.util.EventListener;
+
+public class Parser extends DocumentParser {
+    protected ParserListener listenerList;
+
+    public Parser(Reader src) {
+        super(src);
+    }
+
+    public Parser(InputStream in) {
+        super(in);
+    }
+
+    protected void tag(String name, TagProperties atts, boolean endTag, boolean emptyTag) {
+	Tag tag = new Tag(name, atts, endTag, emptyTag);
+	listenerList.tagFound(new ParserEvent(this, tag));
+    }
+
+    protected void pi(String target, String data) {
+	listenerList.piFound(new ParserEvent(this, target, data));
+    }
+
+    protected void doctype(String root, String publicId, String systemId) {
+	listenerList.doctypeFound(new ParserEvent(this, root, publicId, systemId));
+    }
+
+
+    protected void flush(char [] buf, int offset, int length) { 
+	if (length == 1 &&((buf[offset] == DocPConst.NEWLINE) ||
+			   (buf[offset] == DocPConst.RETURN))) {
+	    return;
+	}
+	String text = new String(buf, offset, length);
+	listenerList.textFound(new ParserEvent(this, text));
+    }
+
+    protected void comment(String s) { 
+	listenerList.commentFound(new ParserEvent(this, s));
+    }
+
+    protected void errorString(String s) { 
+	listenerList.errorFound(new ParserEvent(this, s));
+    } 
+
+    // Not need for our version of Parser
+    protected String documentAttribute(String name) {return null;}
+
+    public void addParserListener(ParserListener l) {
+        listenerList = ParserMulticaster.add(listenerList, l);
+    }
+
+    public void removeParserListener(ParserListener l) {
+        listenerList = ParserMulticaster.remove(listenerList, l);
+    }
+
+    static protected class ParserMulticaster implements ParserListener {
+	protected final EventListener a, b;
+
+	protected ParserMulticaster(EventListener newA, EventListener newB) {
+	    this.a = newA; this.b = newB;
+	}
+
+	protected EventListener remove(EventListener oldl) {
+	    if (oldl == a)  return b;
+	    if (oldl == b)  return a;
+	    EventListener a2 = removeInternal(a, oldl);
+	    EventListener b2 = removeInternal(b, oldl);
+	    if (a2 == a && b2 == b) {
+		return this;	// it's not here
+	    }
+	    return addInternal(a2, b2);
+	}
+
+	protected static EventListener addInternal(EventListener a, EventListener b) {
+	    if (a == null)  return b;
+	    if (b == null)  return a;
+	    return new ParserMulticaster(a, b);
+	}
+
+	protected static EventListener removeInternal(EventListener l, EventListener oldl) {
+	    if (l == oldl || l == null) {
+		return null;
+	    } else if (l instanceof ParserMulticaster) {
+		return ((ParserMulticaster)l).remove(oldl);
+	    } else {
+		return l;		// it's not here
+	    }
+	}
+
+	public void tagFound(ParserEvent e) {
+	    ((ParserListener)a).tagFound(e);
+	    ((ParserListener)b).tagFound(e);
+	}
+
+	public void piFound(ParserEvent e) {
+	    ((ParserListener)a).piFound(e);
+	    ((ParserListener)b).piFound(e);
+	}
+
+	public void doctypeFound(ParserEvent e) {
+	    ((ParserListener)a).doctypeFound(e);
+	    ((ParserListener)b).doctypeFound(e);
+	}
+
+	public void textFound(ParserEvent e) {
+	    ((ParserListener)a).textFound(e);
+	    ((ParserListener)b).textFound(e);
+	}
+
+	public void commentFound(ParserEvent e) {
+	    ((ParserListener)a).commentFound(e);
+	    ((ParserListener)b).commentFound(e);
+	}
+
+	public void errorFound(ParserEvent e) {
+	    ((ParserListener)a).errorFound(e);
+	    ((ParserListener)b).errorFound(e);
+	}
+
+	public static ParserListener add(ParserListener a, ParserListener b) {
+	    return (ParserListener)addInternal(a, b);
+	}
+
+	public static ParserListener remove(ParserListener l, ParserListener oldl) {
+	    return (ParserListener)removeInternal(l, oldl);
+	}
+    } // End of class Parser.ParserMulticaster
+}
diff --git a/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/ParserEvent.java b/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/ParserEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..7319fd119afe38e19201fd4e528650d967844762
--- /dev/null
+++ b/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/ParserEvent.java
@@ -0,0 +1,152 @@
+/*
+ * @(#)ParserEvent.java	1.12 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.java.help.impl;
+
+/**
+ * An event in the HTML/XML Parser
+ *
+ * @author Roger D. Brinkley
+ * @version	1.12	10/30/06
+ */
+
+import java.net.URL;
+import java.util.Vector;
+import java.util.Enumeration;
+
+public class ParserEvent extends java.util.EventObject {
+    private Tag tag;
+    private String text;
+    private String target;
+    private String data;
+    private String root;
+    private String publicId;
+    private String systemId;
+
+    /**
+     * Represents a parsed Tag in the Parser
+     * @see java.help.basic.Parser
+     * 
+     * @param source The Parser this came from
+     * @param tag The parsed Tag.
+     */
+    public ParserEvent(Object source, Tag tag) {
+	super (source);
+	this.tag = tag;
+    }
+
+    /**
+     * Represents a parsed continous block of text, a comment, or an error.
+     * @see java.help.basic.Parser
+     *
+     * @param source The Parser this came from
+     * @param String The text, comment, or error
+     */
+    public ParserEvent(Object source, String text) {
+	super (source);
+	this.text = text;
+    }
+
+    /**
+     * Represents a PI (processing instruction)
+     * @see java.help.basic.Parser
+     *
+     * @param source The Parser this came from
+     * @param target The PI target
+     * @param data The rest of the PI
+     */
+    public ParserEvent(Object source, String target, String data) {
+	super (source);
+	this.target = target;
+	this.data = data;
+    }
+
+    /**
+     * Represents a DOCTYPE
+     * @see java.help.basic.Parser
+     *
+     * @param source The Parser this came from
+     * @param root The root
+     * @param publicId The publicID (may be null)
+     * @param systemID The  systemID (may be null)
+     */
+    public ParserEvent(Object source, String root, String publicId, String systemId) {
+	super (source);
+	this.root = root;
+	this.publicId = publicId;
+	this.systemId = systemId;
+    }
+
+    /**
+     * @return the Tag
+     */
+    public Tag getTag() {
+	return tag;
+    }
+
+    /**
+     * @return the text
+     */
+    public String getText() {
+	return text;
+    }
+
+    /**
+     * @return the target
+     */
+    public String getTarget() {
+	return target;
+    }
+
+    /**
+     * @return the data
+     */
+    public String getData() {
+	return data;
+    }
+
+    /**
+     * @return the root
+     */
+    public String getRoot() {
+	return root;
+    }
+
+    /**
+     * @return the publicId
+     */
+    public String getPublicId() {
+	return publicId;
+    }
+
+    /**
+     * @return the systemId
+     */
+    public String getSystemId() {
+	return systemId;
+    }
+}
diff --git a/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/ParserListener.java b/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/ParserListener.java
new file mode 100644
index 0000000000000000000000000000000000000000..1acec3081cacb71eb03501107fc4bf3828b53e0e
--- /dev/null
+++ b/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/ParserListener.java
@@ -0,0 +1,81 @@
+/*
+ * @(#)ParserListener.java	1.11 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.java.help.impl;
+
+/**
+ * ParserListener defines the interface for an object that listens to 
+ * parsing events in a Parser.
+ *
+ * @author Roger D. Brinkley
+ * @version	1.11	10/30/06
+ */
+
+public interface ParserListener extends java.util.EventListener {
+    /**
+     * This tells the listener that a Tag was parsed
+     *
+     * @param e The event
+     */
+    public void tagFound(ParserEvent e);
+
+    /**
+     * This tells the listener that a PI was parsed
+     *
+     * @param e The event
+     */
+    public void piFound(ParserEvent e);
+
+    /**
+     * This tells the listener that a DOCTYPE was parsed
+     *
+     * @param e The event
+     */
+    public void doctypeFound(ParserEvent e);
+
+    /**
+     * This tells the listener that a continous block of text was parsed
+     *
+     * @param e The event
+     */
+    public void textFound(ParserEvent e);
+
+    /**
+     * This tells the listener that a comment was parsed
+     *
+     * @param e The event
+     */
+    public void commentFound(ParserEvent e);
+
+    /**
+     * This tells the listener that a error was parsed
+     *
+     * @param e The event
+     */
+    public void errorFound(ParserEvent e);
+
+}
diff --git a/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/SwingWorker.java b/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/SwingWorker.java
new file mode 100644
index 0000000000000000000000000000000000000000..1b924f077b341d654d16f241c2a4892bfbcf14c7
--- /dev/null
+++ b/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/SwingWorker.java
@@ -0,0 +1,172 @@
+/*
+ * @(#)SwingWorker.java	1.3 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+/*
+ * @(#) SwingWorker.java 1.3 - last change made 10/30/06
+ */
+
+package com.sun.java.help.impl;
+
+import javax.swing.SwingUtilities;
+
+/**
+ * This is the 3rd version of SwingWorker (also known as
+ * SwingWorker 3), an abstract class that you subclass to
+ * perform GUI-related work in a dedicated thread.  For
+ * instructions on and examples of using this class, see:
+ * 
+ * http://java.sun.com/docs/books/tutorial/uiswing/misc/threads.html
+ *
+ * Note that the API changed slightly in the 3rd version:
+ * You must now invoke start() on the SwingWorker after
+ * creating it.
+ */
+
+public abstract class SwingWorker {
+    private Object value;  // see getValue(), setValue()
+
+    /** 
+     * Class to maintain reference to current worker thread
+     * under separate synchronization control.
+     */
+    private static class ThreadVar {
+        private Thread thread;
+        ThreadVar(Thread t) { thread = t; }
+        synchronized Thread get() { return thread; }
+        synchronized void clear() { thread = null; }
+    }
+
+    private ThreadVar threadVar;
+
+    /** 
+     * Get the value produced by the worker thread, or null if it 
+     * hasn't been constructed yet.
+     */
+    protected synchronized Object getValue() { 
+        return value; 
+    }
+
+    /** 
+     * Set the value produced by worker thread 
+     */
+    private synchronized void setValue(Object x) { 
+        value = x; 
+    }
+
+    /** 
+     * Compute the value to be returned by the <code>get</code> method. 
+     */
+    public abstract Object construct();
+
+    /**
+     * Called on the event dispatching thread (not on the worker thread)
+     * after the <code>construct</code> method has returned.
+     */
+    public void finished() {
+    }
+
+    /**
+     * A new method that interrupts the worker thread.  Call this method
+     * to force the worker to stop what it's doing.
+     */
+    public void interrupt() {
+        Thread t = threadVar.get();
+        if (t != null) {
+            t.interrupt();
+        }
+        threadVar.clear();
+    }
+
+    /**
+     * Return the value created by the <code>construct</code> method.  
+     * Returns null if either the constructing thread or the current
+     * thread was interrupted before a value was produced.
+     * 
+     * @return the value created by the <code>construct</code> method
+     */
+    public Object get() {
+        while (true) {  
+            Thread t = threadVar.get();
+            if (t == null) {
+                return getValue();
+            }
+            try {
+                t.join();
+            }
+            catch (InterruptedException e) {
+                Thread.currentThread().interrupt(); // propagate
+                return null;
+            }
+        }
+    }
+
+
+    /**
+     * Start a thread that will call the <code>construct</code> method
+     * and then exit.
+     */
+    public SwingWorker() {
+        final Runnable doFinished = new Runnable() {
+           public void run() { finished(); }
+        };
+
+        Runnable doConstruct = new Runnable() { 
+            public void run() {
+                try {
+                    setValue(construct());
+                }
+                finally {
+                    threadVar.clear();
+                }
+
+                SwingUtilities.invokeLater(doFinished);
+            }
+        };
+
+        Thread t = new Thread(doConstruct);
+        threadVar = new ThreadVar(t);
+    }
+
+    /**
+     * Start the worker thread.
+     */
+    public void start() {
+	start(Thread.NORM_PRIORITY);
+    }
+	
+    /**
+     * Start the worker thread.
+     */
+    public void start(int priority) {
+        Thread t = threadVar.get();
+        if (t != null) {
+	    if (priority < Thread.MAX_PRIORITY && priority > Thread.MIN_PRIORITY) {
+		t.setPriority(priority);
+	    }
+            t.start();
+        }
+    }
+}
diff --git a/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/Tag.java b/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/Tag.java
new file mode 100644
index 0000000000000000000000000000000000000000..6cfa48369587f7df0b10df40703b97d6c2562c9e
--- /dev/null
+++ b/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/Tag.java
@@ -0,0 +1,77 @@
+/*
+ * @(#)Tag.java	1.8 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @(#) Tag.java 1.8 - last change made 10/30/06
+ */
+
+package com.sun.java.help.impl;
+
+/**
+ * This class contains a reference to a tag in a parsed document, the type of
+ * tag, and the tag's attributes.
+ *
+ * @author Roger D. Brinkley
+ * @version	1.8	10/30/06
+ *
+ * @see Parser
+ * @see HTMLParser
+ */
+
+
+public class Tag {
+
+    /** The name of the tag */
+    public String name;
+
+    /** The type of tag, false if an opening tag or true if a closing tag. */
+    public boolean isEnd;
+
+    /** The type of tag, true if an empty tag. */
+    public boolean isEmpty;
+
+    /** The tag attributes, in identifier, value pairs. */
+    public TagProperties atts;
+
+
+    /**
+     * Sets the tag, position, and type.
+     * @param tag	   the tag descriptor
+     * @param pos	   the position in the text
+     * @param isEnd   true if a &lt;/tag&gt; or &lt;tag/&gt; tag 
+     * @param isEmpty   true if a &lt;tag/&gt; tag
+     * @see Tag
+     **/
+
+    public Tag(String name, TagProperties atts, boolean isEnd, boolean isEmpty) {
+	this.name = name;
+	this.atts = atts;
+	this.isEnd = isEnd;
+	this.isEmpty = isEmpty;
+    }
+
+}
diff --git a/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/TagProperties.java b/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/TagProperties.java
new file mode 100644
index 0000000000000000000000000000000000000000..1f79a4c69b5cff803f0324967b861dc8b0cb22e3
--- /dev/null
+++ b/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/TagProperties.java
@@ -0,0 +1,293 @@
+/*
+ * @(#)TagProperties.java	1.8 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @(#) TagProperties.java 1.8 - last change made 10/30/06
+ */
+package com.sun.java.help.impl;
+
+/**
+ * The <code>TagProperties</code> class represents a persistent set of 
+ * properties. Each key and its corresponding value in 
+ * the property list is a string. 
+ *
+ * @see java.help.Tag
+ */
+
+import java.io.IOException;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+public class TagProperties implements Cloneable {
+
+    protected Hashtable	hashtable;
+    protected int	initialSize;
+
+static int count1 = 0, count2 = 0;
+
+    /**
+     * Creates an empty property list with no default values. 
+     *
+     * @since   JDK1.0
+     */
+    public TagProperties() {
+	this(7);		// Prime number
+    }
+
+    public TagProperties(int initialSize) {
+	this.initialSize = initialSize;
+    }
+
+
+    /**
+     * Searches for the property with the specified key in this property list.
+     * The method returns
+     * <code>null</code> if the property is not found.
+     *
+     * @param   key   the property key.
+     * @return  the value in this property list with the specified key value.
+     * @since   JDK1.0
+     */
+    public String getProperty(String key) {
+	return (String)get(key);
+    }
+
+    /**
+     * Searches for the property with the specified key in this property list.
+     * The method returns the
+     * default value argument if the property is not found.
+     *
+     * @param   key            the hashtable key.
+     * @param   defaultValue   a default value.
+     *
+     * @return  the value in this property list with the specified key value.
+     * @since   JDK1.0
+     */
+    public String getProperty(String key, String defaultValue) {
+	String val = getProperty(key);
+	return (val == null) ? defaultValue : val;
+    }
+
+    /**
+     * Returns an enumeration of all the keys in this property list
+     *
+     * @return  an enumeration of all the keys in this property list
+     * @see     java.util.Enumeration
+     * @since   JDK1.0
+     */
+    public Enumeration propertyNames() {
+	Hashtable h = new Hashtable(11);
+	enumerate(h);
+	return h.keys();
+    }
+
+    /**
+     * Prints this property list out to the specified output stream. 
+     * This method is useful for debugging. 
+     *
+     * @param   out   an output stream.
+     * @since   JDK1.0
+     */
+    public void list(PrintStream out) {
+	out.println("-- listing properties --");
+	Hashtable h = new Hashtable(11);
+	enumerate(h);
+	for (Enumeration e = h.keys() ; e.hasMoreElements() ;) {
+	    String key = (String)e.nextElement();
+	    String val = (String)h.get(key);
+	    if (val.length() > 40) {
+		val = val.substring(0, 37) + "...";
+	    }
+	    out.println(key + "=" + val);
+	}
+    }
+
+    /**
+     * Prints this property list out to the specified output stream. 
+     * This method is useful for debugging. 
+     *
+     * @param   out   an output stream.
+     * @since   JDK1.1
+     */
+    /*
+     * Rather than use an anonymous inner class to share common code, this
+     * method is duplicated in order to ensure that a non-1.1 compiler can
+     * compile this file.
+     */
+    public void list(PrintWriter out) {
+	out.println("-- listing properties --");
+	Hashtable h = new Hashtable(11);
+	enumerate(h);
+	for (Enumeration e = h.keys() ; e.hasMoreElements() ;) {
+	    String key = (String)e.nextElement();
+	    String val = (String)h.get(key);
+	    if (val.length() > 40) {
+		val = val.substring(0, 37) + "...";
+	    }
+	    out.println(key + "=" + val);
+	}
+    }
+
+    /**
+     * Enumerates all key/value pairs in the specified hastable.
+     * @param h the hashtable
+     */
+    private synchronized void enumerate(Hashtable h) {
+	for (Enumeration e = keys() ; e.hasMoreElements() ;) {
+	    String key = (String)e.nextElement();
+	    h.put(key, get(key));
+	}
+    }
+
+    /***** Implementation of a deferred hashtable *****/
+
+    public int size() {
+	if (hashtable != null) {
+	    return hashtable.size();
+	} else {
+	    return 0;
+	}
+    }
+
+    public boolean isEmpty() {
+	if (hashtable != null) {
+	    return hashtable.isEmpty();
+	} else {
+	    return true;
+	}
+    }
+
+    public synchronized Enumeration keys() {
+	if (hashtable != null) {
+	    return hashtable.keys();
+	} else {
+	    return new EmptyEnumerator();
+	}
+    }
+
+    public synchronized Enumeration elements() {
+	if (hashtable != null) {
+	    return hashtable.elements();
+	} else {
+	    return new EmptyEnumerator();
+	}
+    }
+
+    public synchronized boolean contains(Object value) {
+	if (hashtable != null) {
+	    return hashtable.contains(value);
+	} else {
+	    return false;
+	}
+    }
+
+    public synchronized boolean containsKey(Object key) {
+	if (hashtable != null) {
+	    return hashtable.containsKey(key);
+	} else {
+	    return false;
+	}
+    }
+
+    public synchronized Object get(Object key) {
+	if (hashtable != null) {
+	    return hashtable.get(key);
+	} else {
+	    return null;
+	}
+    }
+
+    public synchronized Object put(Object key, Object value) {
+	if (hashtable == null) {
+	    hashtable = new Hashtable(initialSize);
+	}
+	return hashtable.put(key, value);
+    }
+
+    public synchronized Object remove(Object key) {
+	if (hashtable != null) {
+	    return hashtable.remove(key);
+	} else {
+	    return null;
+	}
+    }
+
+    public synchronized void clear() {
+	if (hashtable != null) {
+	    hashtable.clear();
+	}
+    }
+
+    protected void setHashtable(Hashtable t) {
+	hashtable = t;
+    }
+
+    /**
+     * HERE - we probably should use plain Hashtable instead of TagProperties
+     */
+    public Hashtable getHashtable() {
+	return hashtable;
+    }
+
+    public synchronized Object clone() {
+	try { 
+	    TagProperties tp = (TagProperties)super.clone();
+	    if (hashtable != null) {
+		tp.setHashtable((Hashtable)hashtable.clone());
+	    }
+	    return tp;
+	} catch (CloneNotSupportedException e) { 
+	    // this shouldn't happen, since we are Cloneable
+	    throw new InternalError();
+	}
+    }
+
+    public synchronized String toString() {
+	if (hashtable != null) {
+	    return hashtable.toString();
+	} else {
+	    return "{ }";
+	}
+    }
+
+    class EmptyEnumerator implements Enumeration {
+	
+	public boolean hasMoreElements() {
+	    return false;
+    }
+	
+	public Object nextElement() {
+	    throw new java.util.NoSuchElementException("EmptyEnumerator");
+	}
+    }
+
+}
+
diff --git a/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/ViewAwareComponent.java b/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/ViewAwareComponent.java
new file mode 100644
index 0000000000000000000000000000000000000000..6f9204a4c0e72bdf8442316de198e12eae2a2eae
--- /dev/null
+++ b/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/ViewAwareComponent.java
@@ -0,0 +1,53 @@
+/*
+ * @(#)ViewAwareComponent.java	1.5 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.java.help.impl;
+
+import javax.swing.text.*;
+
+/**
+ * Interface that a Component should support if it wants to play in the View
+ * hierachy.
+ *
+ * WARNING!! This is an experimental feature of the JavaHelp reference
+ * implemenation and may change in future versions of the implementation.
+ *
+ * @author Eduardo Pelegri-Llopart
+ * @version 1.5 10/30/06 */
+
+
+public interface ViewAwareComponent {
+    /**
+     * Set the View that corresponds to this object
+     * This gives access to a wealth of information.
+     */
+    public void setViewData(View v);
+
+    /**
+    * May need something to react to changes (in my view?)
+    */
+}
diff --git a/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/XmlReader.java b/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/XmlReader.java
new file mode 100644
index 0000000000000000000000000000000000000000..23a75168e26b4a7840ed897ba911fedcd47a7322
--- /dev/null
+++ b/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/XmlReader.java
@@ -0,0 +1,803 @@
+/*
+ * @(#)XmlReader.java	1.5 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+/*
+ * @(#) XmlReader.java 1.5 - last change made 10/30/06
+ */
+
+package com.sun.java.help.impl;
+
+import java.io.*;
+import java.net.URLConnection;
+
+/**
+ * This handles several XML-related tasks that normal java.io Readers
+ * don't support, inluding use of IETF standard encoding names and
+ * automatic detection of most XML encodings.  The former is needed
+ * for interoperability; the latter is needed to conform with the XML
+ * spec.  This class also optimizes reading some common encodings by
+ * providing low-overhead unsynchronized Reader support.
+ *
+ * <P> Note that the autodetection facility should be used only on
+ * data streams which have an unknown character encoding.  For example,
+ * it should never be used on MIME text/xml entities.
+ *
+ * <P> Note that XML processors are only required to support UTF-8 and
+ * UTF-16 character encodings.  Autodetection permits the underlying Java
+ * implementation to provide support for many other encodings, such as
+ * ISO-8859-5, Shift_JIS, EUC-JP, and ISO-2022-JP.
+ *
+ * @author David Brownell
+ * @author Roger D. Brinkley
+ * @version 1.24
+ */
+
+final public class XmlReader extends Reader
+{
+    private boolean		closed;
+    private InputStreamReader	in;
+
+    //
+    // This class either handles reading itself, in common encodings
+    // (US-ASCII, ISO-Latin-1, UTF-8) or delegates to another Reader.
+    //
+    // Autodetection requires reading/buffering part of the XML declaration,
+    // then potentially switching _after entire characters are read_ to
+    // delegate further operations to such a Reader.  The reader will get
+    // no header (e.g. no UTF-16 Byte Order Mark).  This can work since,
+    // XML declarations contain only ASCII characters, which are a subset
+    // of many encodings (Shift_JIS, ISO-8859-*, EUC-*, ISO-2022-*, more).
+    // 
+    // It's got do this efficiently:  character I/O is solidly on the
+    // critical path.  Synchronization isn't needed, and buffering must
+    // as always be done only with care.  (So keep buffer length over
+    // 2 Kbytes to avoid excess buffering, since most URL handlers stuff
+    // a BufferedInputStream between here and the real data source.  That
+    // class tries to be smart enough not to try buffering if you ask for
+    // more data than it could buffer for you.)
+    //
+    private InputStream		raw;
+    private byte		buffer [];
+    private boolean		isASCII, isLatin1;
+    private int			offset, length;
+
+    // 2nd half of UTF-8 surrogate pair
+    private char		nextChar;
+    
+    private int			switchover;
+    private String		encodingAssigned;
+
+    /**
+     * Constructs the reader from a URLConnection. Uses the encoding 
+     * specified in the HTTP header or autodetects
+     * the encoding to use according to the heuristic specified
+     * in the XML 1.0 recommendation.
+     *
+     * @param uc the URLConnection from which the reader is constructed
+     * @exception IOException on error
+     * @exception UnsupportedEncodingException when the input stream
+     *  is not in an encoding which is supported; this is a fatal XML
+     *  error.
+     */
+    public static Reader createReader (URLConnection uc) throws IOException
+    {
+	String encoding = getEncodingFromContentType(uc.getContentType());
+	if (encoding == null) {
+	    return createReader (uc.getInputStream());
+	}
+	return createReader (uc.getInputStream(), encoding);
+    }
+
+    /**
+     * Gets the encoding from the content type string.
+     * If there is a charset definition specified as a parameter
+     * of the content type specification, it will be used when
+     * loading input streams using the associated XmlReader.
+     * For example if the type is specified as 
+     * <code>text/xml; charset=EUC-JP</code> the Reader will
+     * use the <code>EUC-JP</code> charset for translating
+     * to unicode.
+     * 
+     * @param type the non-null mime type for the content editing
+     *   support.
+     */
+    private static String getEncodingFromContentType(String type) {
+
+	debug ("type=" + type);
+	// The type could have optional info is part of it,
+	// for example some charset info.  We need to strip that
+	// of and save it.
+	if (type == null) {
+	    return null;
+	}
+	int parm = type.indexOf(";");
+	if (parm > -1) {
+	    // Save the paramList.
+	    String paramList = type.substring(parm);
+	    // update the content type string.
+	    type = type.substring(0, parm).trim();
+	    if (type.compareTo("text/xml") == 0) {
+		// Set the charset name from the paramlist
+		return getCharsetFromContentTypeParameters(paramList);
+	    }
+	}
+	return null;
+    }
+
+    /**
+     * This method get's the charset information specified as part
+     * of the content type in the http header information.
+     */
+    private static String getCharsetFromContentTypeParameters(String paramlist) {
+	String charset = null;
+	try {
+	    // paramlist is handed to us with a leading ';', strip it.
+	    int semi = paramlist.indexOf(';');
+	    if (semi > -1 && semi < paramlist.length()-1) {
+		paramlist = paramlist.substring(semi + 1);
+	    }
+
+	    if (paramlist.length() > 0) {
+		// parse the paramlist into attr-value pairs & get the
+		// charset pair's value
+		HeaderParser hdrParser = new HeaderParser(paramlist);
+		charset = hdrParser.findValue("charset");
+		return charset;
+	    }
+	}
+	catch (IndexOutOfBoundsException e) {
+	    // malformed parameter list, use charset we have
+	}
+	catch (NullPointerException e) {
+	    // malformed parameter list, use charset we have
+	}
+	catch (Exception e) {
+	    // malformed parameter list, use charset we have; but complain
+	    System.err.println("Indexer.getCharsetFromContentTypeParameters failed on: " + paramlist);
+	    e.printStackTrace();
+	}
+	return charset;
+    }
+
+    /**
+     * Constructs the reader from an input stream, autodetecting
+     * the encoding to use according to the heuristic specified
+     * in the XML 1.0 recommendation.
+     *
+     * @param in the input stream from which the reader is constructed
+     * @exception IOException on error
+     * @exception UnsupportedEncodingException when the input stream
+     *  is not in an encoding which is supported; this is a fatal XML
+     *  error.
+     */
+    public static Reader createReader (InputStream in) throws IOException
+    {
+	return new XmlReader (in);
+    }
+
+    /**
+     * Creates a reader supporting the given encoding, mapping
+     * from standard encoding names to ones that understood by
+     * Java where necessary.
+     *
+     * @param in the input stream from which the reader is constructed
+     * @param encoding the IETF standard name of the encoding to use;
+     *	if null, autodetection is used.
+     * @exception IOException on error
+     * @exception UnsupportedEncodingException when the input stream
+     *  is not in an encoding which is supported; this is a fatal XML
+     *  error.
+     */
+    public static Reader createReader (InputStream in, String encoding)
+    throws IOException
+    {
+	if (encoding == null)
+	    return new XmlReader (in);
+
+	// UTF-16 == ISO-10646-UCS-2 plus surrogates.
+	// The sun.io "Unicode" encoders/decoders don't check
+	// for correctly paired surrogates, so they accept UTF-16.
+
+	if ("UTF-16".equalsIgnoreCase (encoding)
+		|| "ISO-106460-UCS-2".equalsIgnoreCase (encoding))
+	    encoding = "Unicode";
+	else if ("UTF-8".equalsIgnoreCase (encoding))
+	    return new XmlReader (in, "UTF-8");
+	else if ("EUC-JP".equalsIgnoreCase (encoding))
+	    encoding = "EUCJIS";	// works on JDK 1.1 and 1.2
+	else if (isAsciiName (encoding))
+	    return new XmlReader (in, "US-ASCII");
+	else if (isLatinName (encoding))
+	    return new XmlReader (in, "ISO-8859-1");
+
+	// XXX we should provide provide better "unsupported encoding"
+	// diagnostics than this produces...
+	return new InputStreamReader (in, encoding);
+    }
+
+    private XmlReader (InputStream in, String encoding)
+    throws IOException
+    {
+	buffer = new byte [8 * 1024];
+	length = 0;
+	raw = in;
+	if ("US-ASCII".equals (encoding))
+	    setASCII ();
+	else if ("ISO-8859-1".equals (encoding))
+	    setLatin1 ();
+	else if (!"UTF-8".equals (encoding))
+	    throw new UnsupportedEncodingException (encoding);
+	else
+	    setUTF8 ();
+    }
+
+    private static boolean isAsciiName (String encoding)
+    {
+	return "US-ASCII".equalsIgnoreCase (encoding)
+		|| "ASCII".equalsIgnoreCase (encoding);
+    }
+
+    private static boolean isLatinName (String encoding)
+    {
+	return "ISO-8859-1".equalsIgnoreCase (encoding)
+		|| "Latin1".equalsIgnoreCase (encoding)
+		|| "8859_1".equalsIgnoreCase (encoding);
+    }
+
+    private void setASCII ()
+    {
+	encodingAssigned = "US-ASCII";
+	isASCII = true;
+	isLatin1 = false;
+	offset = 0;
+    }
+
+    private void setLatin1 ()
+    {
+	encodingAssigned = "ISO-8859-1";
+	isASCII = false;
+	isLatin1 = true;
+	offset = 0;
+    }
+
+    private void setUTF8 ()
+    {
+	encodingAssigned = "UTF-8";
+	isASCII = false;
+	isLatin1 = false;
+	offset = 0;
+    }
+
+    /** Returns the (non)standard name of the encoding in use */
+    public String getEncoding ()
+    {
+	return encodingAssigned;
+    }
+
+    private XmlReader (InputStream in) throws IOException
+    {
+        int                 c;
+
+	//
+	// Set up buffering ... we buffer at least the XML text
+	// declaration (if it's there), and for some encodings we
+	// manage bulk character I/O.  We can reset within this
+	// buffer so long as we've not assigned the encoding.
+	//
+        raw = in;
+	switchover = -1;
+	buffer = new byte [8 * 1024];
+	offset = length = 0;
+	isLatin1 = true;
+
+        //
+        // See if we can figure out the character encoding used
+        // in this file by peeking at the first few bytes.  If not,
+        // we may be able to look at the whole XML declaration.
+        //
+        switch ((c = read ())) {
+            case 0:
+              // 00 3c 00 3f == illegal UTF-16 big-endian
+              if ((c = read ()) == 0x3c
+                      && (c = read ()) == 0x00
+                      && (c = read ()) == 0x3f) {
+		  setSwitchover ("UnicodeBig");
+		  // no BOM to ignore
+                  return;
+              }
+
+              // 00 00 00 3c == UCS-4 big endian
+              // 00 00 3c 00 == UCS-4 unusual "2143" order
+              // 00 3c 00 00 == UCS-4 unusual "3412" order
+              // ... or something else!  note that only some parts
+	      // of UCS-4 work with UNICODE based systems.
+	      throw new UnsupportedEncodingException ("UCS-4 (?)");
+
+            case '<':      // 0x3c: the most common cases!
+              switch ((c = read ())) {
+                // First character is '<'; could be XML without
+		// an XML directive such as "<hello>", "<!-- ...",
+		// and so on.  Default intelligently; the byte we
+		// just read could be _part_ of a UTF-8 character!
+                default:
+                  break;
+
+                // 3c 00 3f 00 == illegal UTF-16 little endian
+                // 3c 00 00 00 == UCS-4 little endian
+                case 0x00:
+                  if (read () == 0x3f && read () == 0x00) {
+		      setSwitchover ("UnicodeLittle");
+		      // no BOM to ignore
+                      return;
+                  }
+                  throw new UnsupportedEncodingException ("UCS-4");
+
+                // 3c 3f 78 6d == ASCII and supersets '<?xm'
+                case '?': 
+                  if (read () != 'x' || read () != 'm'
+			  || read () != 'l' || read () != ' ')
+		      break;
+		  //
+		  // One of several encodings could be used:
+                  // Shift-JIS, ASCII, UTF-8, ISO-8859-*, etc
+		  //
+		  guessEncoding ();
+                  return;
+              }
+	      break;
+
+            // UTF-16 big-endian
+            case 0xfe:
+              if ((c = read ()) != 0xff)
+                  break;
+	      setSwitchover ("UnicodeBig");
+	      offset = 2;	// skip BOM
+              return;
+
+            // UTF-16 little-endian
+            case 0xff:
+              if ((c = read ()) != 0xfe)
+                  break;
+	      setSwitchover ("UnicodeLittle");
+	      offset = 2;	// skip BOM
+              return;
+
+            // EOF
+            case -1:
+	      return;
+
+            // default ... no XML declaration
+            default:
+              break;
+        }
+
+	//
+        // If all else fails, assume XML without a declaration, and
+        // using UTF-8 encoding.  We must be prepared to re-interpret
+	// bytes we've already read as parts of UTF-8 characters, so
+	// we can't use the "switchover" technique (which works only
+	// "between" characters).
+	//
+	setUTF8 ();
+    }
+
+    // When the buffered input is done, switch to a reader
+    // that can decode data in that encoding.  Only call this
+    // routine after entire characters have been scanned.
+    private void setSwitchover (String encoding) throws IOException
+    {
+	switchover = offset;
+	encodingAssigned = encoding;
+	offset = 0;
+    }
+
+    // we've consumed our buffer, now switch over to a reader
+    // which will decode the rest of the (non-ASCII) input
+    private void doSwitchover () throws IOException
+    {
+	if (offset != switchover)
+	    throw new InternalError ();
+	in = new InputStreamReader (raw, encodingAssigned);
+	buffer = null;
+	switchover = -1;
+    }
+
+
+    /*
+     * Used for ASCII supersets ... including the default UTF-8 encoding.
+     */
+    private void guessEncoding () throws IOException
+    {
+	//
+	// We know that "<?xml " has been seen; so we'll skip any
+	// 	S? version="..." 	[or single quotes]
+	// bit and get the 
+	// 	S? encoding="..." 	[or single quotes]
+	// parts.  We place an arbitrary limit on the amount of text we
+	// expect to find in the XML declarations; excessive whitespace
+	// will cause this to guess "UTF-8".
+	//
+	int		c;
+	StringBuffer	buf = new StringBuffer ();
+	StringBuffer	keyBuf = null;
+	String		key = null;
+	boolean		sawEq = false;
+	char		quoteChar = 0;
+	boolean		sawQuestion = false;
+
+    XmlDecl:
+	for (int i = 0; i < 100; ++i) {
+	    if ((c = read ()) == -1) {
+		setASCII ();
+		return;
+	    }
+
+	    // ignore whitespace before/between "key = 'value'"
+	    if (Character.isWhitespace ((char) c))
+		continue;
+	    
+	    // terminate the loop ASAP
+	    if (c == '?')
+		sawQuestion = true;
+	    else if (sawQuestion) {
+		if (c == '>')
+		    break;
+		sawQuestion = false;
+	    }
+	    
+	    // did we get the "key =" bit yet?
+	    if (key == null || !sawEq) {
+		if (keyBuf == null) {
+		    if (Character.isWhitespace ((char) c))
+			continue;
+		    keyBuf = buf;
+		    buf.setLength (0);
+		    buf.append ((char)c);
+		    sawEq = false;
+		} else if (Character.isWhitespace ((char) c)) {
+		    key = keyBuf.toString ();
+		} else if (c == '=') {
+		    if (key == null)
+			key = keyBuf.toString ();
+		    sawEq = true;
+		    keyBuf = null;
+		    quoteChar = 0;
+		} else
+		    keyBuf.append ((char)c);
+		continue;
+	    }
+
+	    // space before quoted value
+	    if (Character.isWhitespace ((char) c))
+		continue;
+	    if (c == '"' || c == '\'') {
+		if (quoteChar == 0) {
+		    quoteChar = (char) c;
+		    buf.setLength (0);
+		    continue;
+		} else if (c == quoteChar) {
+		    if ("encoding".equals (key)) {
+			String	encoding = buf.toString ();
+
+			// [81] Encname ::= [A-Za-z] ([A-Za-z0-9._]|'-')*
+			for (i = 0; i < encoding.length(); i++) {
+			    c = encoding.charAt (i);
+			    if ((c >= 'A' && c <= 'Z')
+				    || (c >= 'a' && c <= 'z'))
+				continue;
+			    if (i > 0 && (c == '-'
+				    || (c >= '0' && c <= '9')
+				    || c == '.' || c == '_'))
+				continue;
+			    // map errors to UTF-8 default
+			    break XmlDecl;
+			}
+
+			// we handle ASCII directly
+			if (isAsciiName (encoding)) {
+			    setASCII ();
+			    return;
+			}
+
+			// ditto ISO 8859/1
+			if (isLatinName (encoding)) {
+			    setLatin1 ();
+			    return;
+			}
+
+			// and UTF-8
+			if ("UTF-8".equalsIgnoreCase (encoding)
+				|| "UTF8".equalsIgnoreCase (encoding)
+				)
+			    break XmlDecl;
+
+			// JDK uses nonstandard names internally
+			if ("EUC-JP".equalsIgnoreCase (encoding))
+			    encoding = "EUCJIS";
+
+			// other encodings ... use a reader.
+			setSwitchover (encoding);
+			return;
+		    } else {
+			key = null;
+			continue;
+		    }
+		}
+	    }
+	    buf.append ((char) c);
+	}
+
+	setUTF8 ();
+    }
+
+    /*
+     * Converts a UTF-8 character from the input buffer, optionally
+     * restricting to the US-ASCII subset of UTF-8.
+     */
+    private char	utf8char () throws IOException
+    {
+    	char		retval;
+    	int		character;
+    	
+	// return second half of a surrogate pair
+    	if (nextChar != 0) {
+    	    retval = nextChar;
+    	    nextChar = 0;
+    	    return retval;
+    	}
+    	
+    	//
+    	// Excerpted from RFC 2279:
+    	//
+	// UCS-4 range (hex.)    UTF-8 octet sequence (binary)
+	// 0000 0000-0000 007F   0xxxxxxx
+	// 0000 0080-0000 07FF   110xxxxx 10xxxxxx
+	// 0000 0800-0000 FFFF   1110xxxx 10xxxxxx 10xxxxxx
+	// 0001 0000-001F FFFF   11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+	// 0020 0000-03FF FFFF   111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
+	// 0400 0000-7FFF FFFF   1111110x 10xxxxxx ... 10xxxxxx
+	//
+	// The last two encodings (5 and 6 bytes per char) aren't allowed
+	// in XML documents since the characters are out of range.
+	//
+	retval = (char) buffer [offset];
+	if ((retval & 0x80) == 0x00) {			// 1 byte
+	    offset++;
+	    return retval;
+	}
+	if (isASCII)
+	    throw new CharConversionException ("Not US-ASCII:  0x"
+			+ Integer.toHexString (retval & 0xff));
+	
+	//
+	// Multibyte sequences -- check offsets optimistically,
+	// ditto the "10xx xxxx" format for non-initial bytes
+	//
+	int		off = offset;
+	
+	try {
+	    if ((buffer [off] & 0x0E0) == 0x0C0) {		// 2 bytes
+		character  = (buffer [off++] & 0x1f) << 6;
+		character +=  buffer [off++] & 0x3f;
+		retval = (char) character;
+		character = 0;
+	    } else if ((buffer [off] & 0x0F0) == 0x0E0) {	// 3 bytes
+		character  = (buffer [off++] & 0x0f) << 12;
+		character += (buffer [off++] & 0x3f) << 6;
+		character +=  buffer [off++] & 0x3f;
+		retval = (char) character;
+		character = 0;
+	    } else if ((buffer [off] & 0x0f8) == 0x0F0) {	// 4 bytes
+		character  = (buffer [off++] & 0x07) << 18;
+		character += (buffer [off++] & 0x3f) << 12;
+		character += (buffer [off++] & 0x3f) << 6;
+		character +=  buffer [off++] & 0x3f;
+		// Convert UCS-4 char to a Unicode surrogate pair
+		character -= 0x10000;
+		retval = (char) (0xD800 + (character >> 10));
+		character = 0xDC00 + (character & 0x03ff);
+	    } else
+		// XXX actually a WF error ...
+		throw new CharConversionException ("Illegal XML character"
+		    + " 0x" + Integer.toHexString (buffer [offset] & 0xff)
+		);
+
+	} catch (ArrayIndexOutOfBoundsException e) {
+	    // that is, off > length && length >= buffer.length
+	    retval = (char) 0;
+	    character = 0;
+	}
+
+	//
+	// if the buffer held only a partial character, compact it
+	// and try to read the rest of the character.  worst case
+	// involves three single-byte reads.
+	//
+	if (off > length) {
+	    System.arraycopy (buffer, offset, buffer, 0, length - offset);
+	    length -= offset;
+	    offset = 0;
+	    off = raw.read (buffer, length, buffer.length - length);
+	    if (off < 0)
+		throw new CharConversionException ("Partial UTF-8 char");
+	    length += off;
+	    return utf8char ();
+	}
+
+	//
+	// check the format of the non-initial bytes, and return
+	//
+	for (offset++; offset < off; offset++)
+	    if ((buffer [offset] & 0xC0) != 0x80)
+		throw new CharConversionException ("Malformed UTF-8 char");
+	nextChar = (char) character;
+	return retval;
+    }
+
+    /**
+     * Reads the number of characters read into the buffer, or -1 on EOF.
+     */
+    public int read (char buf [], int off, int len) throws IOException
+    {
+	int	i;
+
+	if (closed)
+	    return -1;
+	if (switchover > 0 && offset == switchover)
+	    doSwitchover ();
+	if (in != null)
+	    return in.read (buf, off, len);
+
+	if (offset >= length) {
+	    offset = 0;
+	    length = raw.read (buffer, 0, buffer.length);
+	}
+	if (length <= 0)
+	    return -1;
+	if (encodingAssigned == null || isLatin1)
+	    for (i = 0; i < len && offset < length; i++)
+		buf [off++] = (char) (buffer [offset++] & 0xff);
+	else
+	    for (i = 0; i < len && offset < length; i++)
+		buf [off++] = utf8char ();
+	return i;
+    }
+
+    /**
+     * Reads a single character.
+     */
+    public int read () throws IOException
+    {
+	if (closed)
+	    return -1;
+	if (switchover > 0 && offset == switchover)
+	    doSwitchover ();
+	if (in != null)
+	    return in.read ();
+
+	if (offset >= length) {
+	    if (encodingAssigned == null) {
+		// minimize readahead we might regret...
+		if (length == buffer.length)
+		    throw new InternalError ("too much peekahead");
+		int len = raw.read (buffer, offset, 1);
+		if (len <= 0)
+		    return -1;
+		length += len;
+	    } else {
+		offset = 0;
+		length = raw.read (buffer, 0, buffer.length);
+		if (length <= 0)
+		    return -1;
+	    }
+	}
+
+	if (isLatin1 || encodingAssigned == null)
+	    return buffer [offset++] & 0x0ff;
+	else
+	    return utf8char ();
+    }
+
+    /**
+     * Returns true iff the reader supports mark/reset.
+     */
+    public boolean markSupported ()
+    {
+	return in != null && in.markSupported ();
+    }
+
+    /**
+     * Sets a mark allowing a limited number of characters to
+     * be "peeked", by reading and then resetting.
+     * @param value how many characters may be "peeked".
+     */
+    public void mark (int value) throws IOException
+    {
+	if (in != null)
+	    in.mark (value);
+    }
+
+    /**
+     * Resets the current position to the last marked position.
+     */
+    public void reset () throws IOException
+    {
+	if (in != null)
+	    in.reset ();
+    }
+
+    /**
+     * Skips a specified number of characters.
+     */
+    public long skip (long value) throws IOException
+    {
+	if (value < 0)
+	    return 0;
+	if (in != null)
+	    return in.skip (value);
+	long avail = length - offset;
+	if (avail >= value) {
+	    offset += (int) value;
+	    return value;
+	}
+	offset += avail;
+	return avail + raw.skip (value - avail);
+    }
+
+    /**
+     * Returns true iff input characters are known to be ready.
+     */
+    public boolean ready () throws IOException
+    {
+	if (in != null)
+	    return in.ready ();
+	return (length > offset) || raw.available () != 0;
+    }
+
+    /**
+     * Closes the reader.
+     */
+    public void close () throws IOException
+    {
+	if (closed)
+	    return;
+	if (in != null)
+	    in.close ();
+	else
+	    raw.close ();
+	closed = true;
+    }
+
+    /**
+     * For printf debugging.
+     */
+    private static boolean debug = false;
+    private static void debug(String str) {
+        if (debug) {
+            System.out.println("XmlReader: " + str);
+        }
+    }
+}
diff --git a/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/package.html b/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/package.html
new file mode 100644
index 0000000000000000000000000000000000000000..42320a02191dd6efa178e9b8ceb2e0c849de84ab
--- /dev/null
+++ b/jhMaster/JavaHelp/src/impl/com/sun/java/help/impl/package.html
@@ -0,0 +1,57 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<!--
+
+  @(#)package.html 1.1 10/15/98
+
+  Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+  DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+  This code is free software; you can redistribute it and/or modify it
+  under the terms of the GNU General Public License version 2 only, as
+  published by the Free Software Foundation.  Sun designates this
+  particular file as subject to the "Classpath" exception as provided
+  by Sun in the LICENSE file that accompanied this code.
+
+  This code is distributed in the hope that it will be useful, but WITHOUT
+  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+  version 2 for more details (a copy is included in the LICENSE file that
+  accompanied this code).
+
+  You should have received a copy of the GNU General Public License version
+  2 along with this work; if not, write to the Free Software Foundation,
+  Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+  Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+  CA 95054 USA or visit www.sun.com if you need additional information or
+  have any questions.
+
+-->
+
+</head>
+<body bgcolor="white">
+
+Implementation classes for JavaHelp.
+This classes are private and are not intented to be used by programmers
+and can change without any notice.
+
+<p>
+<em>Note:</em>We have not yet finalized the location for these classes.
+
+<!--
+<H2>Package Specification</H2>
+Link to updated API specification to be added here.
+-->
+
+<H2>Related Documentation</H2>
+
+<P>
+For overviews, tutorials, examples, guides, tool support,
+and other documentation,
+please see
+<A HREF="http://java.sun.com/products/javahelp/">the JavaHelp home page</A>
+
+  </body>
+</html>
diff --git a/jhMaster/JavaHelp/src/new/javax/help/AbstractHelpAction.java b/jhMaster/JavaHelp/src/new/javax/help/AbstractHelpAction.java
new file mode 100644
index 0000000000000000000000000000000000000000..18d9e30a824f010b146e157f3a35c05444e1a265
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/AbstractHelpAction.java
@@ -0,0 +1,148 @@
+/*
+ * @(#)AbstractHelpAction.java	1.2 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help;
+
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
+import java.util.Hashtable;
+
+/**
+ *
+ * @author Stepan Marek
+ * @version	1.2	10/30/06
+ */
+public abstract class AbstractHelpAction implements HelpAction {
+        
+    AbstractHelpAction(Object control, String name) {
+        this.control = control;
+        putValue("name", name);
+    }
+    
+    /** Holds value of property enabled. */
+    private boolean enabled = true;
+    
+    /** Holds value of property control. */
+    private Object control;
+    
+    private Hashtable table;
+    
+    /** Utility field used by bound properties. */
+    private PropertyChangeSupport propertyChangeSupport;;
+    
+    /** Add a PropertyChangeListener to the listener list.
+     * @param l The listener to add.
+     */
+    public synchronized void addPropertyChangeListener(PropertyChangeListener l) {
+        if (propertyChangeSupport == null) {
+            propertyChangeSupport =  new PropertyChangeSupport(this);
+        }
+        propertyChangeSupport.addPropertyChangeListener(l);
+    }
+    
+    /** Removes a PropertyChangeListener from the listener list.
+     * @param l The listener to remove.
+     */
+    public synchronized void removePropertyChangeListener(PropertyChangeListener l) {
+        if (propertyChangeSupport == null) {
+            propertyChangeSupport =  new PropertyChangeSupport(this);
+        }
+        propertyChangeSupport.removePropertyChangeListener(l);
+    }
+
+    /**
+     * Supports reporting bound property changes.  This method can be called
+     * when a bound property has changed and it will send the appropriate
+     * <code>PropertyChangeEvent</code> to any registered 
+     * <code>PropertyChangeListeners</code>.
+     */
+    protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) {
+        if (propertyChangeSupport == null) {
+            return;
+        }
+        propertyChangeSupport.firePropertyChange(propertyName, oldValue, newValue);
+    }
+    
+    /** Getter for property enabled.
+     * @return Value of property enabled.
+     */
+    public boolean isEnabled() {
+        return enabled;
+    }
+    
+    /** Setter for property enabled.
+     * @param enabled New value of property enabled.
+     */
+    public void setEnabled(boolean enabled) {
+        boolean oldEnabled = this.enabled;
+        this.enabled = enabled;
+        firePropertyChange("enabled", new Boolean(oldEnabled), new Boolean(enabled));
+    }
+    
+    /** Getter for property control.
+     * @return Value of property control.
+     */
+    public Object getControl() {
+        return control;
+    }
+
+    /** 
+     * Gets the <code>Object</code> associated with the specified key.
+     *
+     * @param key a string containing the specified <code>key</code>
+     * @return the binding <code>Object</code> stored with this key; if there
+     *		are no keys, it will return <code>null</code>
+     * @see Action#getValue
+     */
+    public Object getValue(String key) {
+	if (table == null) {
+	    return null;
+	}
+	return table.get(key);
+    }
+    
+    /** 
+     * Sets the <code>Value</code> associated with the specified key.
+     *
+     * @param key  the <code>String</code> that identifies the stored object
+     * @param newValue the <code>Object</code> to store using this key
+     * @see Action#putValue 
+     */
+    public void putValue(String key, Object newValue) {
+	if (table == null) {
+	    table = new Hashtable();
+	}
+        Object oldValue;
+        if (newValue == null) {
+            oldValue = table.remove(key);
+        } else {
+            oldValue = table.put(key, newValue);
+        }
+	firePropertyChange(key, oldValue, newValue);
+    }
+
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/AppendMerge.java b/jhMaster/JavaHelp/src/new/javax/help/AppendMerge.java
new file mode 100644
index 0000000000000000000000000000000000000000..032d859b6a08559ae28b77e779ab2ee9c98c0237
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/AppendMerge.java
@@ -0,0 +1,116 @@
+/*
+ * @(#)AppendMerge.java	1.4 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help;
+
+import javax.swing.tree.*;
+import java.util.*;
+import java.text.*;
+
+/**
+ * Append merge type
+ *
+ * @author Richard Gregor
+ * @version	1.4	10/30/06
+ */
+public class AppendMerge extends Merge{
+
+    /**
+     * Constructs AppendMerge
+     *
+     * @param master The master NavigatorView
+     * @param slave The slave NavigatorView
+     */ 
+    public AppendMerge(NavigatorView master, NavigatorView slave){
+        super(master,slave);
+
+    }
+    
+    /**
+     * Processes append merge
+     *
+     * @param node The master node
+     * @return Merged master node
+     */
+    public TreeNode processMerge(TreeNode node){
+       debug("start merge");
+
+       mergeNodes(node, slaveTopNode);
+       return node;
+    }
+
+
+    /**
+     * Merge Nodes. Merge two nodes according to the Append merging rules 
+     *
+     * @param masterNode The master node to merge with 
+     * @param slaveNode The node to merge into the master
+     */
+    public static void mergeNodes(TreeNode master, TreeNode slave) {
+       DefaultMutableTreeNode masterNode = (DefaultMutableTreeNode)master;
+       DefaultMutableTreeNode slaveNode = (DefaultMutableTreeNode)slave;
+       debug("mergeNodes master=" + MergeHelpUtilities.getNodeName(masterNode) + 
+	     " slave=" + MergeHelpUtilities.getNodeName(slaveNode));       
+       while (slaveNode.getChildCount() > 0) {
+	   DefaultMutableTreeNode slaveNodeChild = 
+	       (DefaultMutableTreeNode)slaveNode.getFirstChild();
+	   masterNode.add(slaveNodeChild);
+	   MergeHelpUtilities.mergeNodeChildren("javax.help.AppendMerge", 
+						slaveNodeChild);
+       }
+    }
+    
+    /**
+     * Merge Node Children. Merge the children of a node according to the
+     * Append merging.
+     *
+     * @param node The parent node from which the children are merged
+     */
+    public static void mergeNodeChildren(TreeNode node) {
+	DefaultMutableTreeNode masterNode = (DefaultMutableTreeNode)node;
+	debug("mergeNodes master=" + MergeHelpUtilities.getNodeName(masterNode));
+	
+	// The rules are there are no rules. Nothing else needs to be done
+	// except for merging through the children
+	for (int i=0; i < masterNode.getChildCount(); i++) {
+	    DefaultMutableTreeNode child = 
+		(DefaultMutableTreeNode)masterNode.getChildAt(i);
+	    if (!child.isLeaf()) {
+		MergeHelpUtilities.mergeNodeChildren("javax.help.AppendMerge",
+						     child);
+	    }
+	}
+    }
+
+    private static boolean debug = false;
+    private static void debug(String msg){
+        if (debug) {
+            System.out.println("AppendMerge :"+msg);
+	}
+    }
+}
+    
diff --git a/jhMaster/JavaHelp/src/new/javax/help/BackAction.java b/jhMaster/JavaHelp/src/new/javax/help/BackAction.java
new file mode 100644
index 0000000000000000000000000000000000000000..63c79465ebb52c1cafde8ba2d4052da5f4bd4ad5
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/BackAction.java
@@ -0,0 +1,188 @@
+/*
+ * @(#)BackAction.java	1.4 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.help.*;
+import javax.help.event.*;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.Stack;
+import javax.swing.*;
+
+/**
+ *
+ * @author Stepan Marek
+ * @version	1.4	10/30/06
+ */
+public class BackAction extends AbstractHelpAction implements MouseListener, HelpHistoryModelListener {
+    
+    private static final String NAME = "BackAction";
+
+    private static final int DELAY = 500;    
+    private Timer timer;
+    private HelpHistoryModel historyModel;
+    
+    /** Creates new BackAction */
+    public BackAction(Object control) {
+        super(control, NAME);
+        if (control instanceof JHelp) {
+            JHelp help = (JHelp)control;
+            historyModel = help.getHistoryModel();
+            historyModel.addHelpHistoryModelListener(this);
+            
+            setEnabled(historyModel.getIndex() > 0);
+            
+            putValue("icon", UIManager.getIcon(NAME + ".icon"));
+            
+	    Locale locale = null;
+	    try {
+		locale = help.getModel().getHelpSet().getLocale();
+	    } catch (NullPointerException npe) {
+		locale = Locale.getDefault();
+	    }
+            putValue("tooltip", HelpUtilities.getString(locale, "tooltip." + NAME));
+            putValue("access", HelpUtilities.getString(locale, "access." + NAME));
+        }
+    }
+
+    /**
+     * Invoked when the mouse exits a component.
+     */
+    public void mouseExited(MouseEvent e) {
+    }
+    
+    /**
+     * Invoked when a mouse button has been released on a component.
+     */
+    public void mouseReleased(MouseEvent e) {
+        if (timer != null) {
+            timer.stop();
+        }
+    }
+    
+    /**
+     * Invoked when a mouse button has been pressed on a component.
+     */
+    public void mousePressed(MouseEvent e) {
+        timer = new Timer(DELAY, new TimeListener(e));
+        timer.start();
+    }
+    
+    /**
+     * Invoked when the mouse has been clicked on a component.
+     */
+    public void mouseClicked(MouseEvent e) {
+        if ((historyModel != null) && isEnabled()) {
+            historyModel.goBack();
+        }
+    }
+    
+    /**
+     * Invoked when the mouse enters a component.
+     */
+    public void mouseEntered(MouseEvent e) {
+    }
+
+    private class TimeListener implements ActionListener {
+        
+        private MouseEvent e;
+        
+        public TimeListener(MouseEvent e) {
+            this.e = e;
+        }
+        
+        public void actionPerformed(ActionEvent evt) {
+            timer.stop();
+            if (BackAction.this.isEnabled()) {
+                BackAction.this.showBackwardHistory(e);
+            }
+        }
+    }
+
+    private class HistoryActionListener implements ActionListener {
+        
+        private int index;
+        
+        public HistoryActionListener(int index) {
+            this.index = index;          
+        }
+        
+        public void actionPerformed(java.awt.event.ActionEvent event) {
+            if(historyModel != null) {
+                historyModel.setHistoryEntry(index);
+            }
+        }        
+    }
+
+    private void showBackwardHistory(MouseEvent e) {
+        
+        JPopupMenu backwardMenu = new JPopupMenu("Backward History");
+        
+        if (historyModel == null) {
+            return;
+        }
+        
+        Stack menuStack = new Stack();
+        Locale locale = ((JHelp)getControl()).getModel().getHelpSet().getLocale();
+        Enumeration items = historyModel.getBackwardHistory().elements();
+        JMenuItem mi = null;
+        //while(items.hasMoreElements()) {
+        for (int i = 0; items.hasMoreElements(); i++) {
+            HelpModelEvent item = (HelpModelEvent)items.nextElement();
+            if (item != null) {
+                String title = item.getHistoryName();
+                if (title == null) {
+                    title = HelpUtilities.getString(locale, "history.unknownTitle");
+                }
+                mi = new JMenuItem(title);
+                //mi.setToolTipText(item.getURL().getPath());
+                mi.addActionListener(new HistoryActionListener(i));
+                menuStack.push(mi);
+            }
+        }
+        int size = menuStack.size();
+        for(int j = 0; j < size; j++) {
+            backwardMenu.add((JMenuItem)menuStack.pop());
+        }
+        // if(e.isPopupTrigger())
+        backwardMenu.show(e.getComponent(),e.getX(),e.getY());
+    }
+    
+    /**
+     * Tells the listener that the history has changed.
+     * Will enable/disable the Action depending on the events previous flag
+     *
+     * @param e The HelpHistoryModelEvent
+     */
+    public void historyChanged(HelpHistoryModelEvent e) {
+        setEnabled(e.isPrevious());
+    }
+    
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/BadIDException.java b/jhMaster/JavaHelp/src/new/javax/help/BadIDException.java
new file mode 100644
index 0000000000000000000000000000000000000000..c9083494904972810de5a760234be9210c770ff6
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/BadIDException.java
@@ -0,0 +1,79 @@
+/*
+ * @(#)BadIDException.java	1.15 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help;
+
+/**
+ * An ID was attempted to be created with incorrect arguments
+ *
+ * @author Roger D. Brinkley
+ * @author Eduardo Pelegri-Llopart
+ * @version	1.15	10/30/06
+ */
+
+public class BadIDException extends IllegalArgumentException {
+    private Map map;
+    private String id;
+    private HelpSet hs;
+
+    /**
+     * Create the exception. Null values are allowed for each parameter.
+     * 
+     * @param map The Map in which the ID wasn't found
+     * @param msg A generic message
+     * @param id The ID in Map that wasn't found
+     * @see javax.help.Map
+     */
+    public BadIDException(String msg, Map map, String id, HelpSet hs) {
+	super(msg);
+	this.map = map;
+	this.id = id;
+	this.hs = hs;
+    }
+
+    /**
+     * The HelpSet in which the ID wasn't found
+     */
+    public Map getMap() {
+	return map;
+    }
+
+    /**
+     * The ID that wasn't found in the Map
+     */
+    public String getID() {
+	return id;
+    }
+
+    /**
+     * The HelpSet that wasn't found in the Map
+     */
+    public HelpSet getHelpSet() {
+	return hs;
+    }
+}
+
diff --git a/jhMaster/JavaHelp/src/new/javax/help/CSH.java b/jhMaster/JavaHelp/src/new/javax/help/CSH.java
new file mode 100644
index 0000000000000000000000000000000000000000..07f50b693765b1dec3e97dd54b74abd717ca1ae7
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/CSH.java
@@ -0,0 +1,1729 @@
+/*
+ * @(#)CSH.java	1.50 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help;
+
+import java.lang.reflect.*;
+import javax.help.Map.ID;
+import java.awt.ActiveEvent;
+import java.awt.AWTEvent;
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Cursor;
+import java.awt.EventQueue;
+import java.awt.Frame;
+import java.awt.MenuComponent;
+import java.awt.MenuItem;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.Toolkit;
+import java.awt.Window;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.InputEvent;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseEvent;
+import javax.swing.CellRendererPane;
+import javax.swing.JComponent;
+import javax.swing.JList;
+import javax.swing.JLayeredPane;
+import javax.swing.JMenu;
+import javax.swing.JMenuItem;
+import javax.swing.JPopupMenu;
+import javax.swing.JRootPane;
+import javax.swing.JTable;
+import javax.swing.JTree;
+import javax.swing.SwingUtilities;
+import javax.swing.UIManager;
+import javax.swing.tree.TreePath;
+import javax.swing.table.JTableHeader;
+import javax.swing.table.TableCellRenderer;
+import javax.swing.table.TableColumn;
+import javax.swing.table.TableColumnModel;
+import java.applet.Applet;
+import java.net.URL;
+import java.util.Stack;
+import java.util.Hashtable;
+import java.util.Vector;
+import java.util.Enumeration;
+import java.util.WeakHashMap;
+import java.lang.ref.WeakReference;
+
+/**
+ * A convenience class that provides simple
+ * access to context-senstive help functionality. It creates a default JavaHelp
+ * viewer as well as ActionListeners for "Help" keys, on-item help, and
+ * help buttons.
+ *
+ * @author Roger D. Brinkley
+ * @author Eduardo Pelegri-Llopart
+ * @author Stepan Marek
+ * @version	1.50	10/30/06
+ *
+ */
+public class CSH {
+    
+    static private java.util.Map comps;
+    static private java.util.Map parents;
+    static private java.util.Vector managers = new Vector();
+    
+    /**
+     * Registers the specified manager to maintain dynamic CSH.
+     * @param m the CSH manager
+     * @since 2.0
+     */
+    public static void addManager(Manager m) {
+        managers.add(m);
+    }
+    
+    /**
+     * Registers the specified manager to maintain dynamic CSH at the specified
+     * position in list of managers.
+     * @param i index at which specified manager is to be inserted.
+     * @param m the CSH manager
+     * @exception ArrayIndexOutOfBoundsException index out of range
+     *            (i &lt; 0 || i &gt;= CSH.getManagerCount()).
+     * @since 2.0
+     */
+    public static void addManager(int i, Manager m) {
+        managers.add(i, m);
+    }
+    
+    /**
+     * Removes the first occurrence of the specified manager in manager list.
+     * @param m manager to be removed from the list, if present.
+     * @return <code>true</code> if the list contained the specified manager.
+     * @since 2.0
+     */
+    public static boolean removeManager(Manager m) {
+        return managers.remove(m);
+    }
+    
+    /**
+     * Removes the manager at the specified position in manager list.
+     * @param i the index of the manager to removed.
+     * @exception ArrayIndexOutOfBoundsException index out of range
+     *            (i &lt; 0 || i &gt;= CHS.getManagerCount()).
+     * @since 2.0
+     */
+    public static void removeManager(int i) {
+        managers.remove(i);
+    }
+    
+    /**
+     * Removes all managers from manager list.
+     * @since 2.0
+     */
+    public static void removeAllManagers() {
+        managers.clear();
+    }
+    
+    /**
+     * Returns the manager at the specified position in manager list.
+     * @param i index of manager to return.
+     * @exception ArrayIndexOutOfBoundsException index is out of range
+     *            (i &lt; 0 || i &gt;= CSH.getManagerCount()).
+     * @since 2.0
+     */
+    public static Manager getManager(int i) {
+        return (Manager)managers.get(i);
+    }
+    
+    /**
+     * Returns array of managers registered to maintain dynamic CSH.
+     *
+     * @return an array containing the managers.
+     * @exception ArrayStoreException the runtime type of a manager is not a
+     *            <code>CSH.Manager</code>
+     * @since 2.0
+     */
+    public static Manager[] getManagers() {
+        return (Manager[])managers.toArray(new Manager[0]);
+    }
+    
+    /**
+     * Returns the number of managers registered to maintain dynamic CSH.
+     *
+     * @return  the number of managers.
+     * @since 2.0
+     */
+    public static int getManagerCount() {
+        return managers.size();
+    }
+    
+    /**
+     * Store HelpID String for an object.
+     * @exception IllegalArgumentException comp is neither <code>Component</code> nor
+     * <code>MenuItem</code>.
+     */
+    private static void _setHelpIDString(Object comp, String helpID) {
+        
+        if (comp instanceof JComponent) {
+            
+            // For JComponents just use client property
+            ((JComponent)comp).putClientProperty("HelpID", helpID);
+            
+        } else if ((comp instanceof Component) || (comp instanceof MenuItem)) {
+            // For MenuItems and Components we have an internal Hashtable of
+            // components and their properties.
+            
+            // Initialize as necessary
+            if (comps == null) {
+                comps = new WeakHashMap(5);
+            }
+            
+            // See if this component has already set some client properties
+            // If so update.
+            // If not then create the client props (as needed) and add to
+            // the internal Hashtable of components and properties
+            Hashtable clientProps = (Hashtable) comps.get(comp);
+            if (clientProps != null) {
+                if (helpID != null) {
+                    clientProps.put("HelpID", helpID);
+                } else {
+                    clientProps.remove("HelpID");
+                    if (clientProps.isEmpty()) {
+                        comps.remove(comp);
+                    }
+                }
+            } else {
+                // Only create properties if there is a valid helpID
+                if (helpID != null) {
+                    clientProps = new Hashtable(2);
+                    clientProps.put("HelpID", helpID);
+                    comps.put(comp, clientProps);
+                }
+            }
+            
+        } else {
+            throw new IllegalArgumentException("Invalid Component");
+        }
+    }
+    
+    /**
+     * Returns the static HelpID for given object.
+     * @exception IllegalArgumentException comp is neither <code>Component</code> nor
+     * <code>MenuItem</code>.
+     */
+    private static String _getHelpIDString(Object comp) {
+        String helpID = null;
+        if (comp != null) {
+            if (comp instanceof JComponent) {
+                helpID = (String) ((JComponent)comp).getClientProperty("HelpID");
+            } else if ((comp instanceof Component) || (comp instanceof MenuItem)) {
+                if (comps != null) {
+                    Hashtable clientProps = (Hashtable)comps.get(comp);
+                    if (clientProps !=null) {
+                        helpID = (String) clientProps.get("HelpID");
+                    }
+                }
+            } else {
+                throw new IllegalArgumentException("Invalid Component");
+            }
+        }
+        return helpID;
+    }
+    
+    
+    /**
+     * Returns the dynamic HelpID for an object.
+     * @exception IllegalArgumentException comp is neither <code>Component</code> nor
+     * <code>MenuItem</code>.
+     */
+    private static String _getHelpIDString(Object comp, AWTEvent evt) {
+        String helpID = null;
+        if (comp != null) {
+            Manager managers[] = getManagers();
+            for (int i = 0; i < managers.length; i++) {
+                helpID = managers[i].getHelpIDString(comp, evt);
+                if (helpID != null) {
+                    return helpID;
+                }
+            }
+        }
+        return null;
+    }
+    
+    /**
+     * Returns ancestor for an object.
+     * @exception IllegalArgumentException comp is neither <code>Component</code> nor
+     * <code>MenuItem</code>.
+     */
+    private static Object getParent(Object comp) {
+        
+        if (comp == null) {
+            return null;
+        }
+        
+        Object parent = null;
+        if (comp instanceof MenuComponent) {
+            parent = ((MenuComponent)comp).getParent();
+        } else if (comp instanceof JPopupMenu) {
+            parent = ((JPopupMenu)comp).getInvoker();
+        } else if (comp instanceof Component) {
+            parent = ((Component)comp).getParent();
+        } else {
+            throw new IllegalArgumentException("Invalid Component");
+        }
+        
+        if (parent == null && parents != null) {
+            parent = parents.get(comp);
+        }
+        
+        return parent;
+    }
+    
+    
+    /**
+     * Sets the helpID for a Component.
+     * If helpID is null this method removes the helpID from the component.
+     * @exception IllegalArgumentException comp is neither <code>Component</code> nor
+     */
+    public static void setHelpIDString(Component comp, String helpID) {
+        _setHelpIDString(comp, helpID);
+    }
+    
+    /**
+     * Sets the helpID for a MenuItem.
+     * If helpID is null, this method removes the helpID from the component.
+     * @exception IllegalArgumentException comp is neither <code>Component</code> nor
+     */
+    public static void setHelpIDString(MenuItem comp, String helpID) {
+        _setHelpIDString(comp, helpID);
+    }
+    
+    /**
+     * Returns the dynamic HelpID for a object. The method passes the arguments
+     * into all registered CSH manageres to obtain dynamic HelpID. If no manager
+     * provides HelpID for the object, the static HelpID is returned or traverse
+     * to the component's ancestors for help.
+     * @exception IllegalArgumentException comp is neither <code>Component</code> nor
+     * <code>MenuItem</code>.
+     * @since 2.0
+     */
+    public static String getHelpIDString(Object comp, AWTEvent evt) {
+        
+        if (comp == null) {
+            return null;
+        }
+        
+        String helpID = _getHelpIDString(comp, evt);
+        
+        if (helpID == null) {
+            helpID = _getHelpIDString(comp);
+        }
+        
+        if (helpID == null) {
+            helpID = getHelpIDString(getParent(comp), evt);
+        }
+        
+        return helpID;
+    }
+    
+    /**
+     * Returns the static helpID for a component.
+     * If the component doesn't have associated help, traverse the
+     * component's ancestors for help.<p>
+     *
+     * This method calls <code>CSH.getHelpIDString(comp, null)</code>.
+     *
+     * @see #setHelpIDString(Component, String)
+     */
+    public static String getHelpIDString(Component comp) {
+        return getHelpIDString(comp, null);
+        
+        /*
+         if (comp == null) {
+            return null;
+        }
+         
+        String helpID = _getHelpIDString(comp);
+         
+        // return the helpID if it exists
+        if (helpID != null) {
+            return helpID;
+        }
+         
+        // loop through the parents to try to find a valid helpID
+        Component parent = null;
+        if (comp instanceof JPopupMenu) {
+            parent = ((JPopupMenu)comp).getInvoker();
+        } else {
+            parent = comp.getParent();
+        }
+         
+        if (parent == null && parents != null) {
+            parent = (Component)parents.get(comp);
+        }
+         
+        if (parent != null) {
+            return getHelpIDString(parent);
+        } else {
+            return null;
+        }
+         */
+    }
+    
+    /**
+     * Returns the static helpID for a MenuItem.
+     * If the component doesn't have associated help, traverse the
+     * component's ancestors for help.<p>
+     *
+     * This method calls <code>CSH.getHelpIDString(comp, null)</code>.
+     *
+     * @see #setHelpIDString(MenuItem, String)
+     */
+    public static String getHelpIDString(MenuItem comp) {
+        return getHelpIDString(comp, null);
+        
+        /*
+        String helpID = _getHelpIDString(comp);
+        // return the helpID if it exists
+        if (helpID != null) {
+            return helpID;
+        }
+         
+        // loop through the parents to try to find a valid helpID
+        MenuContainer parent = comp.getParent();
+        if (parent instanceof MenuItem) {
+            return getHelpIDString((MenuItem)parent);
+        } else {
+            return null;
+        }
+         */
+    }
+    
+    
+    /**
+     * Store HelpSet for an object.
+     * @exception IllegalArgumentException comp is neither <code>Component</code> nor
+     * <code>MenuItem</code>.
+     */
+    private static void _setHelpSet(Object comp, HelpSet hs) {
+        
+        if (comp instanceof JComponent) {
+            
+            // For JComponents just use client property
+            ((JComponent)comp).putClientProperty("HelpSet", hs);
+            
+        } else if ((comp instanceof Component) || (comp instanceof MenuItem)) {
+            
+            // For MenuItem and Components we have an internal Hashtable of
+            // components and their properties.
+            
+            // Initialize as necessary
+            if (comps == null) {
+                comps = new WeakHashMap(5);
+            }
+            
+            // See if this component has already set some client properties
+            // If so update.
+            // If not then create the client props (as needed) and add to
+            // the internal Hashtable of components and properties
+            Hashtable clientProps = (Hashtable) comps.get(comp);
+            if (clientProps != null) {
+                if (hs != null) {
+                    clientProps.put("HelpSet", hs);
+                } else {
+                    clientProps.remove("HelpSet");
+                    if (clientProps.isEmpty()) {
+                        comps.remove(comp);
+                    }
+                }
+            } else {
+                // Only create properties if there is a valid helpID
+                if (hs != null) {
+                    clientProps = new Hashtable(2);
+                    clientProps.put("HelpSet", hs);
+                    comps.put(comp, clientProps);
+                }
+            }
+        } else {
+            throw new IllegalArgumentException("Invalid Component");
+        }
+    }
+    
+    /**
+     * Returns the static HelpSet for an object.
+     * @exception IllegalArgumentException comp is neither <code>Component</code> nor
+     * <code>MenuItem</code>.
+     */
+    private static HelpSet _getHelpSet(Object comp) {
+        HelpSet hs = null;
+        if (comp != null) {
+            if (comp instanceof JComponent) {
+                hs = (HelpSet) ((JComponent)comp).getClientProperty("HelpSet");
+            } else if ((comp instanceof Component) || (comp instanceof MenuItem)) {
+                if (comps != null) {
+                    Hashtable clientProps = (Hashtable)comps.get(comp);
+                    if (clientProps !=null) {
+                        hs = (HelpSet) clientProps.get("HelpSet");
+                    }
+                }
+            } else {
+                throw new IllegalArgumentException("Invalid Component");
+            }
+        }
+        return hs;
+    }
+    
+    /**
+     * Returns the dynamic HelpSet for an object.
+     * @exception IllegalArgumentException comp is neither <code>Component</code> nor
+     * <code>MenuItem</code>.
+     */
+    private static HelpSet _getHelpSet(Object comp, AWTEvent evt) {
+        HelpSet hs = null;
+        if (comp != null) {
+            Manager[] managers = getManagers();
+            for (int i = 0; i < managers.length; i++) {
+                hs = managers[i].getHelpSet(comp, evt);
+                if (hs != null) {
+                    return hs;
+                }
+            }
+        }
+        return hs;
+    }
+    
+    /**
+     * Sets the static HelpSet for a Component.
+     * If HelpSet is null, this method removes the HelpSet
+     * from the component.
+     */
+    public static void setHelpSet(Component comp, HelpSet hs) {
+        _setHelpSet(comp, hs);
+    }
+    
+    /**
+     * Sets the static HelpSet for a MenuItem.
+     * If HelpSet is null, this method removes the HelpSet
+     * from the component.
+     */
+    public static void setHelpSet(MenuItem comp, HelpSet hs) {
+        _setHelpSet(comp, hs);
+    }
+    
+    /**
+     * Returns the dynamic HelpSet for an object.
+     * HelpSets are stored in conjunction with helpIDs. It is possible for a
+     * object to have a helpID without a HelpSet, but a object cannot have a HelpSet
+     * without a helpID.
+     * If the component doesn't have an associated helpID, traverse the
+     * component's ancestors for a helpID. If the componet has a helpID but
+     * doesn't have a HelpSet, return null.
+     *
+     * @exception IllegalArgumentException comp is neither <code>Component</code> nor
+     * <code>MenuItem</code>.
+     *
+     * @see getHelpID
+     */
+    public static HelpSet getHelpSet(Object comp, AWTEvent evt) {
+        
+        if (comp == null) {
+            return null;
+        }
+        
+        String helpID = _getHelpIDString(comp, evt);
+        if (helpID == null) {
+            helpID = _getHelpIDString(comp);
+        }
+        
+        if (helpID != null) {
+            HelpSet hs = _getHelpSet(comp, evt);
+            if (hs == null) {
+                hs = _getHelpSet(comp);
+            }
+            return hs;
+        }
+        
+        return (getHelpSet(getParent(comp), evt));
+    }
+    
+    /**
+     * Returns the static HelpSet for a Component.
+     * HelpSets are stored in conjunction with helpIDs. It is possible for a
+     * Component to have
+     * a helpID without a HelpSet, but a Component cannot have a HelpSet
+     * without a helpID.
+     * If the component doesn't have an associated helpID, traverse the
+     * component's ancestors for a helpID. If the componet has a helpID but
+     * doesn't have a HelpSet, return null.<p>
+     *
+     * This method calls <code>CSH.getHelpSet(comp, null)</code>.
+     *
+     * @see getHelpID
+     * @exception IllegalArgumentException comp is not <code>Component</code
+     */
+    public static HelpSet getHelpSet(Component comp) {
+        return getHelpSet(comp, null);
+        
+        /*
+         if (comp == null) {
+            return null;
+        }
+         
+        String helpID = _getHelpIDString(comp);
+         
+        if (helpID != null) {
+            HelpSet hs = _getHelpSet(comp);
+            if (hs != null) {
+                return hs;
+            }
+        }
+         
+        Component parent = null;
+        if (comp instanceof JPopupMenu) {
+            parent = ((JPopupMenu)comp).getInvoker();
+        } else {
+            parent = comp.getParent();
+        }
+         
+        if (parent == null && parents != null) {
+            parent = (Component)parents.get(comp);
+        }
+         
+        if (parent != null) {
+            return getHelpSet(parent);
+        } else {
+            return null;
+        }
+         */
+    }
+    
+    
+    /**
+     * Returns the static HelpSet for a MenuItem.
+     * HelpSets are stored in conjunction with helpIDs. It is possible for a
+     * MenuItem to have a helpID without a HelpSet, but a MenuItem
+     * cannot have a HelpSet without a helpID.
+     * If the component doesn't have an associated helpID, traverse the
+     * component's ancestors for a helpID. If the componet has a helpID, but
+     * doesn't have a HelpSet return null.
+     *
+     * This method calls <code>CSH.getHelpIDString(comp, null)</code>.
+     * @exception IllegalArgumentException comp is not <code>MenuItem</code>
+     *
+     * @see getHelpID
+     */
+    public static HelpSet getHelpSet(MenuItem comp) {
+        return getHelpSet(comp, null);
+        
+        /*
+         if (comp == null) {
+            return null;
+        }
+         
+        String helpID = _getHelpIDString(comp);
+         
+        if (helpID != null) {
+            HelpSet hs = _getHelpSet(comp);
+            if (hs != null) {
+                return hs;
+            }
+        }
+         
+        MenuContainer parent = comp.getParent();
+        if (parent instanceof MenuItem) {
+            return getHelpSet((MenuItem)parent);
+        } else {
+            return null;
+        }
+         */
+    }
+    
+    /**
+     * Context Sensitive Event Tracking
+     *
+     * Creates a new EventDispatchThread from which to dispatch events. This
+     * method returns when stopModal is invoked.
+     *
+     * @return Object The object on which the event occurred. Null if
+     * cancelled on an undetermined object.
+     */
+    public static Object trackCSEvents() {
+        MouseEvent e = getMouseEvent();
+        if (e != null) {
+            return getDeepestObjectAt(e.getSource(), e.getX(), e.getY());
+        } else {
+            return null;
+        }
+    }
+
+    /*
+     * Generic displayHelp for all CSH.Display* subclasses
+     * 
+     * @param hb The HelpBroker to display in. Can be null but hs and 
+     *		and presentation must be supplies
+     * @param hs The HelpSet to display in. Can be null if hb != null
+     * @param presentation The Presentation class to display the content in
+     * @param presentationName The named presentation to modify the 
+     *		Presentation class with. In some Presenations this is also
+     *		a "named" Presentation.
+     * @param obj The object for which the help is displayed for
+     * @param source The Window for focusOwner purposes
+     * @param event The event that caused this action.
+     */
+    private static void displayHelp(HelpBroker hb, HelpSet hs, 
+				    String presentation, 
+				    String presentationName, Object obj, 
+				    Object source, AWTEvent event) {
+
+	Presentation pres=null;
+
+	if (hb != null) {
+	    // Start by setting the ownerWindow in the HelpBroker
+	    if (hb instanceof DefaultHelpBroker) {
+		((DefaultHelpBroker)hb).setActivationObject(source);
+	    }
+	} else {
+	    // using a Presentation
+	    // Get a Presentation
+	    ClassLoader loader;
+	    Class klass;
+	    Class types[] = { HelpSet.class,
+			      String.class};
+	    Object args[] = { hs,
+			      presentationName};		
+	    try {
+		loader = hs.getLoader();
+		if (loader == null) {
+		    klass = Class.forName(presentation);
+		} else {
+		    klass = loader.loadClass(presentation);
+		}
+		Method m = klass.getMethod("getPresentation", types);
+		pres = (Presentation)m.invoke(null, args);
+	    } catch (Exception ex) {
+		throw new RuntimeException("error invoking presentation" );
+	    }
+
+	    if (pres == null) {
+		return;
+	    }
+
+	    if (pres instanceof WindowPresentation) {
+		((WindowPresentation)pres).setActivationObject(source);
+	    }
+	    if (pres instanceof Popup && obj instanceof Component) {
+		((Popup)pres).setInvoker((Component)obj);
+	    }
+	}
+
+	    
+	// OK now do the CSH stuff
+	String helpID = null;
+	HelpSet objHS = null;
+	helpID = CSH.getHelpIDString(obj, event);
+	objHS = CSH.getHelpSet(obj, event);
+	if (objHS == null) {
+	    if (hb != null) {
+		objHS = hb.getHelpSet();
+	    } else {
+		objHS = hs;
+	    }
+	}
+	try {
+	    ID id = ID.create(helpID, objHS);
+	    if (id == null) {
+		id = objHS.getHomeID();
+	    }
+	    if (hb != null) {
+		hb.setCurrentID(id);
+		hb.setDisplayed(true);
+	    } else {
+		pres.setCurrentID(id);
+		pres.setDisplayed(true);
+	    }
+	} catch (Exception e2) {
+	    e2.printStackTrace();
+	}
+    }
+
+    /**
+     * Context Sensitive Event Tracking
+     *
+     * Creates a new EventDispatchThread from which to dispatch events. This
+     * method returns when stopModal is invoked.
+     *
+     * @return MouseEvent The mouse event occurred. Null if
+     * cancelled on an undetermined object.
+     */
+    private static MouseEvent getMouseEvent() {
+        // Should the cursor change to a quesiton mark here or
+        // require the user to change the cursor externally to this method?
+        // The problem is that each component can have it's own cursor.
+        // For that reason it might be better to have the user change the
+        // cusor rather than us.
+        
+        // To track context-sensitive events get the event queue and process
+        // the events the same way EventDispatchThread does. Filter out
+        // ContextSensitiveEvents SelectObject & Cancel (MouseDown & ???).
+        // Note: This code only handles mouse events. Accessiblity might
+        // require additional functionality or event trapping
+        
+        // If the eventQueue can't be retrieved, the thread gets interrupted,
+        // or the thread isn't a instanceof EventDispatchThread then return
+        // a null as we won't be able to trap events.
+        try {
+            if (EventQueue.isDispatchThread()) {
+                EventQueue eq = null;
+                
+                // Find the eventQueue. If we can't get to it then just return
+                // null since we won't be able to trap any events.
+                
+                try {
+                    eq = Toolkit.getDefaultToolkit().getSystemEventQueue();
+                } catch (Exception ee) {
+                    debug(ee);
+                }
+                
+                // Safe guard
+                if (eq == null) {
+                    return null;
+                }
+                
+                int eventNumber = -1;
+                
+                // Process the events until an object has been selected or
+                // the context-sensitive search has been canceled.
+                while (true) {
+                    // This is essentially the body of EventDispatchThread
+                    // modified to trap context-senstive events and act
+                    // appropriately
+                    eventNumber++;
+                    AWTEvent event = eq.getNextEvent();
+                    Object src = event.getSource();
+                    // can't call eq.dispatchEvent
+                    // so I pasted it's body here
+                    
+                    // debug(event);
+                    
+                    // Not sure if I should suppress ActiveEvents or not
+                    // Modal dialogs do. For now we will not suppress the
+                    // ActiveEvent events
+                    
+                    if (event instanceof ActiveEvent) {
+                        ((ActiveEvent)event).dispatch();
+                        continue;
+                    }
+                    
+                    if (src instanceof Component) {
+                        // Trap the context-sensitive events here
+                        if (event instanceof KeyEvent) {
+                            KeyEvent e = (KeyEvent) event;
+                            // if this is the cancel key then exit
+                            // otherwise pass all other keys up
+                            if (e.getKeyCode() == KeyEvent.VK_CANCEL ||
+                            e.getKeyCode() == KeyEvent.VK_ESCAPE) {
+                                e.consume();
+                                return null;
+                            } else {
+                                e.consume();
+                                // dispatchEvent(event);
+                            }
+                        } else if (event instanceof MouseEvent) {
+                            MouseEvent e = (MouseEvent) event;
+                            int eID = e.getID();
+                            if ((eID == MouseEvent.MOUSE_CLICKED ||
+                            eID == MouseEvent.MOUSE_PRESSED ||
+                            eID == MouseEvent.MOUSE_RELEASED) &&
+                            SwingUtilities.isLeftMouseButton(e)) {
+                                if (eID == MouseEvent.MOUSE_CLICKED) {
+                                    if (eventNumber == 0) {
+                                        dispatchEvent(event);
+                                        continue;
+                                    }
+                                }
+                                e.consume();
+                                return e;
+                            } else {
+                                e.consume();
+                            }
+                        } else {
+                            dispatchEvent(event);
+                        }
+                    } else if (src instanceof MenuComponent) {
+                        if (event instanceof InputEvent) {
+                            ((InputEvent)event).consume();
+                        }
+                    } else {
+                        System.err.println("unable to dispatch event: " + event);
+                    }
+                }
+            }
+        } catch(InterruptedException e) {
+            debug(e);
+        }
+        debug("Fall Through code");
+        return null;
+    }
+    
+    private static void dispatchEvent(AWTEvent event) {
+        Object src = event.getSource();
+        if (event instanceof ActiveEvent) {
+            // This could become the sole method of dispatching in time.
+            ((ActiveEvent)event).dispatch();
+        } else if (src instanceof Component) {
+            ((Component)src).dispatchEvent(event);
+        } else if (src instanceof MenuComponent) {
+            ((MenuComponent)src).dispatchEvent(event);
+        } else {
+            System.err.println("unable to dispatch event: " + event);
+        }
+    }
+    
+    /**
+     * Gets the higest visible component in a ancestor hierarchy at
+     * specific x,y coordinates
+     */
+    private static Object getDeepestObjectAt(Object parent, int x, int y) {
+        if (parent instanceof Container) {
+            Container cont = (Container)parent;
+            // use a copy of 1.3 Container.findComponentAt
+            Component child = findComponentAt(cont, cont.getWidth(), cont.getHeight(), x, y);
+            if (child != null && child != cont) {
+                if (child instanceof JRootPane) {
+                    JLayeredPane lp = ((JRootPane)child).getLayeredPane();
+                    Rectangle b = lp.getBounds();
+                    child = (Component)getDeepestObjectAt(lp, x - b.x, y - b.y);
+                }
+                if (child != null) {
+                    return child;
+                }
+            }
+        }
+        // if the parent is not a Container then it might be a MenuItem.
+        // But even if it isn't a MenuItem just return the parent because
+        // that's a close as we can come.
+        return parent;
+    }
+    
+    private static Component findComponentAt(Container cont, int width, int height, int x, int y) {
+        synchronized (cont.getTreeLock()) {
+            
+            if (!((x >= 0) && (x < width) && (y >= 0) && (y < height) && cont.isVisible() && cont.isEnabled())) {
+                return null;
+            }
+            
+            Component[] component = cont.getComponents();
+            int ncomponents = cont.getComponentCount();
+            
+            // Two passes: see comment in sun.awt.SunGraphicsCallback
+            for (int i = 0 ; i < ncomponents ; i++) {
+                Component comp = component[i];
+                Rectangle rect = null;
+                
+                if (comp instanceof CellRendererPane) {
+                    Component c = getComponentAt((CellRendererPane)comp, x, y);
+                    if (c != null) {
+                        rect = getRectangleAt((CellRendererPane)comp, x, y);
+                        comp = c;
+                    }
+                }
+                
+                if (comp != null && !comp.isLightweight()) {
+                    if (rect == null || rect.width == 0 || rect.height == 0) {
+                        rect = comp.getBounds();
+                    }
+                    if (comp instanceof Container) {
+                        comp = findComponentAt((Container)comp, rect.width, rect.height, x - rect.x, y - rect.y);
+                    } else {
+                        comp = comp.getComponentAt(x - rect.x, y - rect.y);
+                    }
+                    if (comp != null && comp.isVisible() && comp.isEnabled()) {
+                        return comp;
+                    }
+                }
+            }
+            
+            for (int i = 0 ; i < ncomponents ; i++) {
+                Component comp = component[i];
+                Rectangle rect = null;
+                
+                if (comp instanceof CellRendererPane) {
+                    Component c = getComponentAt((CellRendererPane)comp, x, y);
+                    if (c != null) {
+                        rect = getRectangleAt((CellRendererPane)comp, x, y);
+                        comp = c;
+                    }
+                }
+                
+                if (comp != null && comp.isLightweight()) {
+                    if (rect == null || rect.width == 0 || rect.height == 0) {
+                        rect = comp.getBounds();
+                    }
+                    if (comp instanceof Container) {
+                        comp = findComponentAt((Container)comp, rect.width, rect.height, x - rect.x, y - rect.y);
+                    } else {
+                        comp = comp.getComponentAt(x - rect.x, y - rect.y);
+                    }
+                    if (comp != null && comp.isVisible() && comp.isEnabled()) {
+                        return comp;
+                    }
+                }
+            }
+            return cont;
+        }
+    }
+    
+    /**
+     * Returns the Rectangle enclosing component part that the component
+     * provided by renderer will be draw into.
+     */
+    private static Rectangle getRectangleAt(CellRendererPane cont, int x, int y) {
+        Rectangle rect = null;
+        Container c = cont.getParent();
+        // I can process only this four components at present time
+        if (c instanceof JTable) {
+            rect = getRectangleAt((JTable)c, x, y);
+        } else if (c instanceof JTableHeader) {
+            rect = getRectangleAt((JTableHeader)c, x, y);
+        } else if (c instanceof JTree) {
+            rect = getRectangleAt((JTree)c, x, y);
+        } else if (c instanceof JList) {
+            rect = getRectangleAt((JList)c, x, y);
+        }
+        return rect;
+    }
+    
+    /**
+     * Returns the Component provided by Renderer at x, y coordinates.
+     */
+    private static Component getComponentAt(CellRendererPane cont, int x, int y) {
+        Component comp = null;
+        Container c = cont.getParent();
+        // I can process only this four components at present time
+        if (c instanceof JTable) {
+            comp = getComponentAt((JTable)c, x, y);
+        } else if (c instanceof JTableHeader) {
+            comp = getComponentAt((JTableHeader)c, x, y);
+        } else if (c instanceof JTree) {
+            comp = getComponentAt((JTree)c, x, y);
+        } else if (c instanceof JList) {
+            comp = getComponentAt((JList)c, x, y);
+        }
+        
+        // store reference from comp to CellRendererPane
+        // It is needed for backtrack searching of HelpSet and HelpID
+        // in getHelpSet() and getHelpIDString().
+        if (comp != null) {
+            if (parents == null) {
+                // WeakHashMap of WeakReferences
+                parents = new WeakHashMap(4) {
+                    public Object put(Object key, Object value) {
+                        return super.put(key, new WeakReference(value));
+                    }
+                    public Object get(Object key) {
+                        WeakReference wr = (WeakReference)super.get(key);
+                        if (wr != null) {
+                            return wr.get();
+                        } else {
+                            return null;
+                        }
+                    }
+                };
+            }
+            parents.put(comp, cont);
+        }
+        return comp;
+    }
+    
+    private static Rectangle getRectangleAt(JTableHeader header, int x, int y) {
+        Rectangle rect = null;
+        try {
+            int column = header.columnAtPoint(new Point(x, y));
+            rect = header.getHeaderRect(column);
+        } catch (Exception e) {
+        }
+        return rect;
+    }
+    
+    private static Component getComponentAt(JTableHeader header, int x, int y) {
+        try {
+            
+            if (!(header.contains(x, y) && header.isVisible() && header.isEnabled())) {
+                return null;
+            }
+            
+            TableColumnModel columnModel = header.getColumnModel();
+            int columnIndex = columnModel.getColumnIndexAtX(x);
+            TableColumn column = columnModel.getColumn(columnIndex);
+            
+            TableCellRenderer renderer = column.getHeaderRenderer();
+            if (renderer == null) {
+                renderer = header.getDefaultRenderer();
+            }
+            
+            return renderer.getTableCellRendererComponent(
+            header.getTable(), column.getHeaderValue(), false, false, -1, columnIndex);
+            
+        } catch (Exception e) {
+            // NullPointerException in case of (header == null) or (columnModel == null)
+            // ArrayIndexOutOfBoundsException from getColumn(columnIndex)
+        }
+        return null;
+    }
+    
+    private static Rectangle getRectangleAt(JTable table, int x, int y) {
+        Rectangle rect = null;
+        try {
+            Point point = new Point(x, y);
+            int row = table.rowAtPoint(point);
+            int column = table.columnAtPoint(point);
+            rect = table.getCellRect(row, column, true);
+        } catch (Exception e) {
+        }
+        return rect;
+    }
+    
+    private static Component getComponentAt(JTable table, int x, int y) {
+        try {
+            
+            if (!(table.contains(x, y) && table.isVisible() && table.isEnabled())) {
+                return null;
+            }
+            
+            Point point = new Point(x, y);
+            int row = table.rowAtPoint(point);
+            int column = table.columnAtPoint(point);
+            
+            if (table.isEditing() && table.getEditingRow() == row && table.getEditingColumn() == column) {
+                // Pointed component is provided by TableCellEditor. Editor
+                // component is part of component hierarchy so it is checked
+                // directly in loop in findComponentAt()
+                // comp = table.getEditorComponent();
+                return null;
+            }
+            
+            TableCellRenderer renderer = table.getCellRenderer(row, column);
+            return table.prepareRenderer(renderer, row, column);
+            
+        } catch (Exception e) {
+        }
+        return null;
+    }
+    
+    private static Rectangle getRectangleAt(JTree tree, int x, int y) {
+        Rectangle rect = null;
+        try {
+            TreePath path = tree.getPathForLocation(x, y);
+            rect = tree.getPathBounds(path);
+        } catch (Exception e) {
+        }
+        return rect;
+    }
+    
+    private static Component getComponentAt(JTree tree, int x, int y) {
+        try {
+            
+            TreePath path = tree.getPathForLocation(x, y);
+            
+            if (tree.isEditing() && tree.getSelectionPath() == path) {
+                return null;
+            }
+            
+            int row = tree.getRowForPath(path);
+            Object value = path.getLastPathComponent();
+            boolean isSelected = tree.isRowSelected(row);
+            boolean isExpanded = tree.isExpanded(path);
+            boolean isLeaf = tree.getModel().isLeaf(value);
+            boolean hasFocus= tree.hasFocus() && tree.getLeadSelectionRow() == row;
+            
+            return tree.getCellRenderer().getTreeCellRendererComponent(
+            tree, value, isSelected, isExpanded, isLeaf, row, hasFocus);
+            
+        } catch (Exception e) {
+            return null;
+        }
+    }
+    
+    private static Rectangle getRectangleAt(JList list, int x, int y) {
+        Rectangle rect = null;
+        try {
+            int index = list.locationToIndex(new Point(x, y));
+            rect = list.getCellBounds(index, index);
+        } catch (Exception e) {
+        }
+        return rect;
+    }
+    
+    private static Component getComponentAt(JList list, int x, int y) {
+        try {
+            
+            int index = list.locationToIndex(new Point(x, y));
+            Object value = list.getModel().getElementAt(index);
+            boolean isSelected = list.isSelectedIndex(index);
+            boolean hasFocus = list.hasFocus() && list.getLeadSelectionIndex() == index;
+            
+            return list.getCellRenderer().getListCellRendererComponent(
+            list, value, index, isSelected, hasFocus);
+        } catch (Exception e) {
+            return null;
+        }
+    }
+    
+    /*
+    private static Rectangle getRectangleAt(JComboBox combo, int x, int y) {
+        return combo.getBounds();
+    }
+     
+    private static Component getComponentAt(JComboBox combo, int x, int y) {
+        try{
+            if (combo.isEditable()) {
+                return null;
+            }
+     
+            Object value = combo.getSelectedItem();
+            boolean hasFocus = combo.hasFocus() && !combo.isPopupVisible();
+     
+            // How to get JList for getListCellRendererComponent()?
+            // That's the question...
+            JList list = new JList();
+            return combo.getRenderer().getListCellRendererComponent(
+            list, value, -1, hasFocus, false);
+        } catch (Exception e) {
+            return null;
+        }
+    }
+     */
+    
+    /**
+     * An ActionListener that displays the help of the
+     * object that currently has focus. This method is used
+     * to enable HelpKey action listening for components other than
+     * the RootPane. This listener determines if the
+     * object with the current focus has a helpID. If it does, the helpID
+     * is displayed,
+     * otherwise the helpID on the action's source is displayed (if one exists).
+     *
+     * @see HelpBroker.enableHelpKey
+     */
+    public static class DisplayHelpFromFocus implements ActionListener {
+        
+        private HelpBroker hb = null;
+	private HelpSet hs = null;
+	private String presentation = null;
+	private String presentationName = null;
+         
+        public DisplayHelpFromFocus(HelpBroker hb) {
+            if (hb == null) {
+                throw new NullPointerException("hb");
+            }
+            this.hb = hb;
+        }
+
+	/**
+	 * Create a DisplayHelpFromFocus actionListener for a given
+	 * HelpSet. Display the results in specific Presentation of given
+	 * PresentationName.
+	 *
+	 * @param hs A valid HelpSet.
+	 * @param presention A valid javax.help.Presentation class. Throws
+	 *	an IllegalArgumentException if the presentation class cannot
+	 *	instantiated.
+	 * @param name The name of the presentation. This will retrieve the
+	 *	presentation details from the HelpSet hs if one exists. For
+	 *	some Presentation this name will also indicate the "named"
+	 *	Presentation to display the information in.
+	 * @throws NullPointerException if hs is Null.
+	 * @throws IllegalArgumentException if presentation is not valid.
+	 */
+	public DisplayHelpFromFocus(HelpSet hs,
+				    String presentation,
+				    String presentationName) {
+	    if (hs == null) {
+		throw new NullPointerException("hs");
+	    }
+
+	    ClassLoader loader;
+	    Class klass;
+
+	    try {
+		loader = hs.getLoader();
+		if (loader == null) {
+		    klass = Class.forName(presentation);
+		} else {
+		    klass = loader.loadClass(presentation);
+		}
+	    } catch (Exception ex) {
+		throw new IllegalArgumentException(presentation + "presentation  invalid");
+	    }
+
+	    this.presentation = presentation;
+	    this.presentationName = presentationName;
+	    this.hs = hs;
+	}
+
+        
+        public void actionPerformed(ActionEvent e) {
+            
+            Component src = (Component) e.getSource();
+            // Start by setting the ownerWindow in the HelpBroker
+            if (hb instanceof DefaultHelpBroker) {
+                ((DefaultHelpBroker)hb).setActivationObject(src);
+            }
+            
+            Component comp = CSH.findFocusOwner(src);
+            
+            debug("focusOwner:"+comp);
+            
+            if (comp == null) {
+                comp = src;
+            }
+            
+	    displayHelp(hb, hs, presentation, presentationName, comp, comp, e);
+	}	    
+    }
+    
+    
+    /**
+     * Returns the popup menu which is at the root of the menu system
+     * for this popup menu.
+     *
+     * @return the topmost grandparent <code>JPopupMenu</code>
+     */
+    private static JPopupMenu getRootPopupMenu(JPopupMenu popup) {
+        while((popup != null) &&
+        (popup.getInvoker() instanceof JMenu) &&
+        (popup.getInvoker().getParent() instanceof JPopupMenu)
+        ) {
+            popup = (JPopupMenu) popup.getInvoker().getParent();
+        }
+        return popup;
+    }
+    
+    /**
+     * Returns the deepest focused Component or the deepest JPopupMenu
+     * or the deepest armed MenuItem from JPopupMenu hierarchy.
+     */
+    private static Component findFocusOwner(JPopupMenu popup) {
+        if (popup == null) {
+            return null;
+        }
+        synchronized (popup.getTreeLock()) {
+            if (!popup.isVisible()) {
+                return null;
+            }
+            Component comp = null;
+            for (int i = 0, n = popup.getComponentCount(); i < n; i++) {
+                Component c = popup.getComponent(i);
+                if (c.hasFocus()) {
+                    comp = c;
+                    break;
+                }
+                if (c instanceof JMenu && ((JMenu)c).isPopupMenuVisible()) {
+                    comp = c;
+                }
+                if (c instanceof JMenuItem && ((JMenuItem)c).isArmed()) {
+                    comp = c;
+                }
+            }
+            if (comp instanceof JMenu) {
+                comp = findFocusOwner(((JMenu)comp).getPopupMenu());
+            }
+            if (comp != null) {
+                return comp;
+            }
+        }
+        return popup;
+    }
+    
+    /**
+     * Returns the child component which has focus with respects
+     * of PopupMenu visibility.
+     */
+    private static Component findFocusOwner(Component c) {
+        synchronized (c.getTreeLock()) {
+            
+            if (c instanceof JPopupMenu) {
+                return findFocusOwner(getRootPopupMenu((JPopupMenu)c));
+            }
+            
+            if (c.hasFocus()) {
+                return c;
+            }
+            
+            if (c instanceof Container) {
+                for (int i = 0, n = ((Container)c).getComponentCount(); i < n; i++) {
+                    Component focusOwner = findFocusOwner(((Container)c).getComponent(i));
+                    if (focusOwner != null) {
+                        return focusOwner;
+                    }
+                }
+            }
+            return null;  // Component doesn't have hasFocus().
+        }
+    }
+    
+    /**
+     * An ActionListener that displays help on a
+     * selected object after tracking context-sensitive events.
+     * It is normally activated
+     * from a button. It uses CSH.trackingCSEvents to track context-sensitive
+     * events and when an object is selected it gets
+     * the helpID for the object and displays the helpID in the help viewer.
+     */
+    public static class DisplayHelpAfterTracking implements ActionListener {
+        
+        private HelpBroker hb = null;
+	private HelpSet hs = null;
+	private String presentation = null;
+	private String presentationName = null;
+        
+        public DisplayHelpAfterTracking(HelpBroker hb) {
+            if (hb == null) {
+                throw new NullPointerException("hb");
+            }
+            this.hb = hb;
+        }
+        
+	/**
+	 * Create a DisplayHelpAfterTracking actionListener for a given
+	 * HelpSet. Display the results in specific Presentation of given
+	 * PresentationName.
+	 *
+	 * @param hs A valid HelpSet.
+	 * @param presention A valid javax.help.Presentation class. Throws
+	 *	an IllegalArgumentException if the presentation class cannot
+	 *	instantiated.
+	 * @param name The name of the presentation. This will retrieve the
+	 *	presentation details from the HelpSet hs if one exists. For
+	 *	some Presentation this name will also indicate the "named"
+	 *	Presentation to display the information in.
+	 * @throws NullPointerException if hs is Null.
+	 * @throws IllegalArgumentException if presentation is not valid.
+	 */
+	public DisplayHelpAfterTracking(HelpSet hs,
+					String presentation,
+					String presentationName) {
+	    if (hs == null) {
+		throw new NullPointerException("hs");
+	    }
+
+	    ClassLoader loader;
+	    Class klass;
+
+	    try {
+		loader = hs.getLoader();
+		if (loader == null) {
+		    klass = Class.forName(presentation);
+		} else {
+		    klass = loader.loadClass(presentation);
+		}
+	    } catch (Exception ex) {
+		throw new IllegalArgumentException(presentation + "presentation  invalid");
+	    }
+
+	    this.presentation = presentation;
+	    this.presentationName = presentationName;
+	    this.hs = hs;
+	}
+
+        public void actionPerformed(ActionEvent e) {
+            Cursor onItemCursor, oldCursor;
+            
+            // Make sure that LAF is installed.
+            // It is necessery for UIManager.get("HelpOnItemCursor");
+            SwingHelpUtilities.installUIDefaults();
+            
+            // Get the onItemCursor
+            onItemCursor = (Cursor) UIManager.get("HelpOnItemCursor");
+            if (onItemCursor == null) {
+                return;
+            }
+            
+            // change all the cursors on all windows
+            Vector topComponents = null;
+            cursors = null;
+            
+            if (onItemCursor != null) {
+                cursors = new Hashtable();
+                topComponents = getTopContainers(e.getSource());
+                Enumeration enum1 = topComponents.elements();
+                while (enum1.hasMoreElements()) {
+                    setAndStoreCursors((Container)enum1.nextElement(), onItemCursor);
+                }
+            }
+            
+            MouseEvent event = CSH.getMouseEvent();
+            debug("CSH.getMouseEvent() >>> "+event);
+            
+            if (event != null) {
+                
+                Object obj = CSH.getDeepestObjectAt(event.getSource(), event.getX(), event.getY());
+                debug("CSH.getDeepestObjectAt() >>> "+obj);
+                
+                if (obj != null) {
+
+                    displayHelp(hb, hs, presentation, presentationName,
+				obj, e.getSource(), event);
+		}
+            }
+            
+            // restore the old cursors
+            if (topComponents != null) {
+                Enumeration containers = topComponents.elements();
+                while (containers.hasMoreElements()) {
+                    resetAndRestoreCursors((Container)containers.nextElement());
+                }
+            }
+            cursors = null;
+        }
+        
+        private Hashtable cursors;
+        
+        /*
+         * Get all top level containers to change it's cursors
+         */
+        private static Vector getTopContainers(Object source) {
+            // This method is used to obtain all top level components of application
+            // for which the changing of cursor to question mark is wanted.
+            // Method Frame.getFrames() is used to get list of Frames and
+            // Frame.getOwnedWindows() method on elements of the list
+            // returns all Windows, Dialogs etc. It works correctly in application.
+            // Problem is in applets. There is no way how to get reference to applets
+            // from elsewhere than applet itself. So, if request for CSH (this means
+            // pressing help button or select help menu item) does't come from component
+            // in a Applet, cursor for applets is not changed to question mark. Only for
+            // Frames, Windows and Dialogs is cursor changed properly.
+            
+            Vector containers = new Vector();
+            Component topComponent = null;
+            topComponent = getRoot(source);
+            if (topComponent instanceof Applet) {
+                try {
+                    Enumeration applets = ((Applet)topComponent).getAppletContext().getApplets();
+                    while (applets.hasMoreElements()) {
+                        containers.add(applets.nextElement());
+                    }
+                } catch (NullPointerException npe) {
+                    containers.add(topComponent);
+                }
+            }
+            Frame frames[] = Frame.getFrames();
+            for (int i = 0; i < frames.length; i++) {
+                Window[] windows = frames[i].getOwnedWindows();
+                for (int j = 0; j < windows.length; j++) {
+                    containers.add(windows[j]);
+                }
+                if (!containers.contains(frames[i])) {
+                    containers.add(frames[i]);
+                }
+            }
+            return containers;
+        }
+        
+        
+        private static Component getRoot(Object comp) {
+            Object parent = comp;
+            while (parent != null) {
+                comp = parent;
+                if (comp instanceof MenuComponent) {
+                    parent = ((MenuComponent)comp).getParent();
+                } else if (comp instanceof Component) {
+                    if (comp instanceof Window) {
+                        break;
+                    }
+                    if (comp instanceof Applet) {
+                        break;
+                    }
+                    parent = ((Component)comp).getParent();
+                } else {
+                    break;
+                }
+            }
+            if (comp instanceof Component) {
+                return ((Component)comp);
+            }
+            return null;
+        }
+        
+        
+        /*
+         * Set the cursor for a component and its children.
+         * Store the old cursors for future resetting
+         */
+        private void setAndStoreCursors(Component comp, Cursor cursor) {
+            if (comp == null) {
+                return;
+            }
+            Cursor compCursor = comp.getCursor();
+            if (compCursor != cursor) {
+                cursors.put(comp, compCursor);
+                debug("set cursor on " + comp);
+                comp.setCursor(cursor);
+            }
+            if (comp instanceof Container) {
+                Component component[] = ((Container)comp).getComponents();
+                for (int i = 0 ; i < component.length; i++) {
+                    setAndStoreCursors(component[i], cursor);
+                }
+            }
+        }
+        
+        /*
+         * Actually restore the cursor for a component and its children
+         */
+        private void resetAndRestoreCursors(Component comp) {
+            if (comp == null) {
+                return;
+            }
+            Cursor oldCursor = (Cursor) cursors.get(comp);
+            if (oldCursor != null) {
+                debug("restored cursor " + oldCursor + " on " + comp);
+                comp.setCursor(oldCursor);
+            }
+            if (comp instanceof Container) {
+                Component component[] = ((Container)comp).getComponents();
+                for (int i = 0 ; i < component.length; i++) {
+                    resetAndRestoreCursors(component[i]);
+                }
+            }
+        }
+    }
+    
+    /**
+     * An ActionListener that
+     * gets the helpID for the action source and displays the helpID in the
+     * help viewer.
+     *
+     * @see HelpBroker.enableHelp
+     */
+    public static class DisplayHelpFromSource implements ActionListener {
+        
+        private HelpBroker hb;
+	private HelpSet hs = null;
+	private String presentation = null;
+	private String presentationName = null;
+        
+        public DisplayHelpFromSource(HelpBroker hb) {
+            if (hb == null) {
+                throw new NullPointerException("hb");
+            }
+            this.hb = hb;
+        }
+        
+	/**
+	 * Create a DisplayHelpFromSource actionListener for a given
+	 * HelpSet. Display the results in specific Presentation of given
+	 * PresentationName.
+	 *
+	 * @param hs A valid HelpSet.
+	 * @param presention A valid javax.help.Presentation class. Throws
+	 *	an IllegalArgumentException if the presentation class cannot
+	 *	instantiated.
+	 * @param name The name of the presentation. This will retrieve the
+	 *	presentation details from the HelpSet hs if one exists. For
+	 *	some Presentation this name will also indicate the "named"
+	 *	Presentation to display the information in.
+	 * @throws NullPointerException if hs is Null.
+	 * @throws IllegalArgumentException if presentation is not valid.
+	 */
+	public DisplayHelpFromSource(HelpSet hs,
+				    String presentation,
+				    String presentationName) {
+	    if (hs == null) {
+		throw new NullPointerException("hs");
+	    }
+
+	    ClassLoader loader;
+	    Class klass;
+
+	    try {
+		loader = hs.getLoader();
+		if (loader == null) {
+		    klass = Class.forName(presentation);
+		} else {
+		    klass = loader.loadClass(presentation);
+		}
+	    } catch (Exception ex) {
+		throw new IllegalArgumentException(presentation + "presentation  invalid");
+	    }
+
+	    this.presentation = presentation;
+	    this.presentationName = presentationName;
+	    this.hs = hs;
+	}
+
+        
+        public void actionPerformed(ActionEvent e) {
+	    Object source = e.getSource();
+	    displayHelp(hb, hs, presentation, presentationName, 
+			source, source, e);
+            
+        }
+    }
+    
+    /**
+     * CSH Manager Interface to support dynamic <code>HelpSet</code> and <code>ID</code>
+     * for object. CSH is allowed only for <code>Component</code> and <code>MenuItem</code>.
+     *
+     * @since 2.0
+     */
+    public interface Manager {
+        /**
+         * Returns HelpSet of the object depending on the event.
+         * @param comp The object to get <code>HelpSet</code> for it. Only <code>Component</code>
+         * and <code>MenuItem</code> is allowed.
+         * @param e The event by which dynamic CSH was invoked. It can be <code>MouseEvent</code>
+         * in case of window level CSH, <code>ActionEvent</code> in case of field level CSH or
+         * <code>null</code> otherwise.
+         * @return A HelpSet for given object or null if no HelpSet is assigned to object
+         * @see CSH.DisplayHelpAfterTracking
+         * @see CSH.DisplayHelpFromFocus
+         * @see CSH.DisplayHelpFromSource
+         */
+        public HelpSet getHelpSet(Object comp, AWTEvent e);
+
+        /**
+         * Returns String represent Map.ID of the object depending on the event.
+         * @param comp The object to get <code>Map.ID</code> for it. Only <code>Component</code>
+         * and <code>MenuItem</code> is allowed.
+         * @param e The event by which dynamic CSH was invoked. It can be <code>MouseEvent</code>
+         * in case of window level CSH, <code>ActionEvent</code> in case of field level CSH or
+         * <code>null</code> otherwise.
+         * @return A Map.ID string for given object or null if no Map.ID is assigned to object
+         * @see CSH.DisplayHelpAfterTracking
+         * @see CSH.DisplayHelpFromFocus
+         * @see CSH.DisplayHelpFromSource
+         */
+        public String getHelpIDString(Object comp, AWTEvent e);
+    }
+    
+    /**
+     * Debugging code...
+     */
+    
+    private static final boolean debug = false;
+    private static void debug(Object msg) {
+        if (debug) {
+            System.err.println("CSH: "+msg);
+        }
+    }
+    
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/DefaultHelpBroker.java b/jhMaster/JavaHelp/src/new/javax/help/DefaultHelpBroker.java
new file mode 100644
index 0000000000000000000000000000000000000000..4bc43d4134cbee6cff431993d5a3475167a61ad3
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/DefaultHelpBroker.java
@@ -0,0 +1,779 @@
+/*
+ * @(#)DefaultHelpBroker.java	1.69 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help;
+
+import javax.swing.*;
+import javax.help.*;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.net.URL;
+import java.awt.*;
+import java.awt.event.*;
+import javax.help.Map.ID;
+import java.util.Locale;
+import java.awt.Font;
+import java.awt.Dimension;
+import java.lang.reflect.*;
+
+/**
+ * An implmentation of the HelpBroker interface
+ *
+ * @author Roger Brinkley
+ * @author Eduardo Pelegri-Llopart
+ * @version	1.33	01/25/99
+ */
+
+public class DefaultHelpBroker implements HelpBroker, KeyListener {
+
+    private MainWindow mw = null;
+    private HelpSet helpKeyHS = null;
+    private String helpKeyPresentation = null;
+    private String helpKeyPresentationName = null;
+
+    /**
+     * Constructor
+     */
+
+    public DefaultHelpBroker(HelpSet hs) {
+	mw = (MainWindow) MainWindow.getPresentation(hs, null);
+    }
+
+    /**
+     * Zero-argument constructor.
+     * It should be followed by a setHelpSet() invocation.
+     */
+
+    public DefaultHelpBroker() {
+	mw = (MainWindow) MainWindow.getPresentation(null, null);
+    }
+
+
+    /**
+     * Get the WindowPresentation for this HelpBroker
+     * @returns the window presentation for this object
+     */
+    public WindowPresentation getWindowPresentation() {
+	return mw;
+    }
+
+    /**
+     * Returns the default HelpSet
+     */
+    public HelpSet getHelpSet() {
+	return mw.getHelpSet();
+    }
+
+    /**
+     * Changes the HelpSet for this broker.
+     * @param hs The HelpSet to set for this broker. 
+     * A null hs is valid parameter.
+     */
+    public void setHelpSet(HelpSet hs) {
+	debug ("setHelpSet");
+	mw.setHelpSet(hs);
+    }
+
+    /**
+     * Set the presentation attributes from a HelpSet.Presentation.
+     * The HelpSet.Presentation must be in the current HelpSet.
+     * 
+     * @param hsPres The HelpSet.Presentation
+     * @since 2.0
+     */
+    public void setHelpSetPresentation(HelpSet.Presentation hsPres) {
+	debug ("setHelpSetPresentation");
+	mw.setHelpSetPresentation(hsPres);
+    }
+
+    /**
+     * Gets the locale of this component.
+     * @return This component's locale. If this component does not
+     * have a locale, the defaultLocale is returned.
+     * @see #setLocale
+     */
+    public Locale getLocale() {
+	return mw.getLocale();
+    }
+
+    /**
+     * Sets the locale of this HelpBroker. The locale is propagated to
+     * the presentation.
+     * @param l The locale to become this component's locale. A null locale
+     * is the same as the defaultLocale.
+     * @see #getLocale
+     */
+    public void setLocale(Locale l) { 
+	mw.setLocale(l);
+    }
+
+    /**
+     * Gets the font for this HelpBroker.
+     */
+    public Font getFont () {
+	return mw.getFont();
+    }
+
+    /**
+     * Sets the font for this this HelpBroker.
+     * @param f The font.
+     */
+    public void setFont (Font f) {
+	mw.setFont(f);
+    }
+
+    /**
+     * Set the currentView to the navigator with the same 
+     * name as the <tt>name</tt> parameter.
+     *
+     * @param name The name of the navigator to set as the 
+     * current view. If nav is null or not a valid Navigator 
+     * in this HelpBroker then an 
+     * IllegalArgumentException is thrown.
+     * @throws IllegalArgumentException if nav is null or not a valid Navigator.
+     */
+    public void setCurrentView(String name) {
+	mw.setCurrentView(name);
+    }
+
+    /**
+     * Determines the current navigator.
+     */
+    public String getCurrentView() {
+	return mw.getCurrentView();
+    }
+
+
+    /**
+     * Initializes the presentation.
+     * This method allows the presentation to be initialized but not displayed.
+     * Typically this would be done in a separate thread to reduce the
+     * intialization time.
+     */
+    public void initPresentation() {
+	mw.createHelpWindow();
+    }
+
+    /**
+     * Displays the presentation to the user.
+     */
+    public void setDisplayed(boolean b) {
+	debug("setDisplayed");
+	mw.setDisplayed(b);
+    }
+
+    /**
+     * Determines if the presentation is displayed.
+     */
+    public boolean isDisplayed() {
+	return mw.isDisplayed();
+    }
+
+    /**
+     * Requests the presentation be located at a given position.
+     */
+    public void setLocation(Point p) {
+	mw.setLocation(p);
+    }
+
+    /**
+     * Requests the location of the presentation.
+     * @returns Point the location of the presentation.
+     */
+    public Point getLocation() {
+	return mw.getLocation();
+    }
+
+    /**
+     * Requests the presentation be set to a given size.
+     */
+    public void setSize(Dimension d) {
+	mw.setSize(d);
+    }
+
+    /**
+     * Requests the size of the presentation.
+     * @returns Point the location of the presentation.
+     */
+    public Dimension getSize() throws UnsupportedOperationException {
+	return mw.getSize();
+    }
+
+    /**
+     * Requests the presentation be set to a given screen.
+     */
+    public void setScreen(int screen) {
+	mw.setScreen(screen);
+    }
+
+    /**
+     * Requests the screen of the presentation.
+     * @returns int the screen of the presentation.
+     */
+    public int getScreen() throws UnsupportedOperationException {
+	return mw.getScreen();
+    }
+
+    /**
+     * Hides/Shows view.
+     */
+    public void setViewDisplayed(boolean displayed) {
+	mw.setViewDisplayed(displayed);
+    }
+
+    /**
+     * Determines if the current view is visible.
+     */
+    public boolean isViewDisplayed() {
+	return mw.isViewDisplayed();
+    }
+
+    /**
+     * Shows this ID.
+     *
+     * @param id A string that identifies the topic to show for the loaded (top) HelpSet
+     * @param presentation The Presentation class to display the Help in.
+     * @param presentationName The name of a Presentation section from a 
+     *		HelpSet to use. For some Presentations this will also be
+     *		the name to apply to the Presentation.
+     * @exception BadIDException The ID is not valid for the HelpSet
+     * @exception IllegalArgumentException if presentation is not valid
+     * @see Presentation
+     */
+    public void showID(String id, String presentation, 
+		       String presentationName) throws BadIDException {
+	debug("showID - string");
+	Presentation pres = getPresentation(presentation, presentationName);
+	if (pres != null) {
+	    pres.setCurrentID(id);
+	    pres.setDisplayed(true);
+	}
+    }
+
+    /**
+     * Show this ID.
+     *
+     * @param id a Map.ID indicating the URL to display
+     * @param presentation The Presentation class to display the Help in.
+     * @param presentationName The name of a Presentation section from a 
+     *		HelpSet to use. For some Presentations this will also be
+     *		the name to apply to the Presentation.
+     * @exception InvalidHelpSetContextException if the current helpset does not contain
+     * id.helpset
+     * @see Presentation
+     */
+    public void showID(ID id, String presentation, String presentationName) 
+	throws InvalidHelpSetContextException {
+	debug("showID - ID");
+	Presentation pres = getPresentation(presentation, presentationName);
+	if (pres != null) {
+	    pres.setCurrentID(id);
+	    pres.setDisplayed(true);
+	}
+    }
+
+    private Presentation getPresentation(String presentation,
+					 String presentationName) {
+	Presentation pres;
+
+	HelpSet hs = mw.getHelpSet();
+	// should never happen, but...
+	if (hs == null) {
+	    return null;
+	}
+	ClassLoader loader;
+	Class klass;
+	Class types[] = { HelpSet.class,
+			  String.class};
+	Object args[] = { hs,
+			  presentationName};		
+	try {
+	    loader = hs.getLoader();
+	    if (loader == null) {
+		klass = Class.forName(presentation);
+	    } else {
+		klass = loader.loadClass(presentation);
+	    }
+	    Method m = klass.getMethod("getPresentation", types);
+	    pres = (Presentation)m.invoke(null, args);
+	} catch (ClassNotFoundException cnfex) {
+	    throw new IllegalArgumentException(presentation + "presentation  invalid");
+	} catch (Exception ex) {
+	    throw new RuntimeException("error invoking presentation" );
+	}
+
+	if (pres == null) {
+	    return null;
+	}
+
+	// It is not possible to call this method for Popup
+	if (pres instanceof Popup) {
+	    return null;
+	}
+	
+	return pres;
+    }
+
+    /**
+     * Shows this ID as content relative to the (top) HelpSet for the HelpBroker
+     * instance--HelpVisitListeners are notified.
+     *
+     * @param id A string that identifies the topic to show for the loaded (top) HelpSet
+     * @exception BadIDException The ID is not valid for the HelpSet
+     */
+    public void setCurrentID(String id) throws BadIDException {
+	debug("setCurrentID - string");
+	mw.setCurrentID(id);
+    }
+
+    /**
+     * Displays this ID--HelpVisitListeners are notified.
+     *
+     * @param id a Map.ID indicating the URL to display
+     * @exception InvalidHelpSetContextException if the current helpset does not contain
+     * id.helpset
+     */
+    public void setCurrentID(ID id) throws InvalidHelpSetContextException {
+	debug("setCurrentID - ID");
+	mw.setCurrentID(id);
+    }
+
+    /**
+     * Determines which ID is displayed (if any).
+     */
+    public ID getCurrentID() {
+	return mw.getCurrentID();
+    }
+
+    /**
+     * Displays this URL.
+     * HelpVisitListeners are notified.
+     * The currentID changes if there is a mathing ID for this URL
+     * @param url The url to display. A null URL is a valid url.
+     */
+    public void setCurrentURL(URL url) {
+	debug ("setCurrentURL");
+	mw.setCurrentURL(url);
+    }
+
+    /**
+     * Determines which URL is displayed.
+     */
+    public URL getCurrentURL() {
+	return mw.getCurrentURL();
+    }
+
+
+    // Context-Senstive methods
+    /**
+     * Enables the Help key on a Component. This method works best when
+     * the component is the
+     * rootPane of a JFrame in Swing implementations, or a java.awt.Window
+     * (or subclass thereof) in AWT implementations.
+     * This method sets the default
+     * helpID and HelpSet for the Component and registers keyboard actions
+     * to trap the "Help" keypress. When the "Help" key is pressed, if the
+     * object with the current focus has a helpID, the helpID is displayed.
+     * otherwise the default helpID is displayed.
+     *
+     * @param comp the Component to enable the keyboard actions on.
+     * @param id the default HelpID to be displayed
+     * @param hs the default HelpSet to be displayed. If hs is null the default HelpSet
+     * will be assumed.
+     * 
+     * @see getHelpKeyActionListener
+     * @see enableHelpKey(Component, String, HelpSet, String, String);
+     */
+    public void enableHelpKey(Component comp, String id, HelpSet hs) {
+	enableHelpKey(comp, id, hs, null, null);
+    }
+
+    /**
+     * Enables the Help key on a Component. This method works best when
+     * the component is the
+     * rootPane of a JFrame in Swing implementations, or a java.awt.Window
+     * (or subclass thereof) in AWT implementations.
+     * This method sets the default
+     * helpID and HelpSet for the Component and registers keyboard actions
+     * to trap the "Help" keypress. When the "Help" key is pressed, if the
+     * object with the current focus has a helpID, the helpID is displayed.
+     * otherwise the default helpID is displayed.
+     *
+     * @param comp the Component to enable the keyboard actions on.
+     * @param id the default HelpID to be displayed
+     * @param hs the default HelpSet to be displayed. If hs is null the 
+     *		default HelpSet from the HelpBroker is assummed. null is not
+     *		valid if presenation is not null.
+     * @param presentation The Presentation class to display the content in.
+     *		If presentation is null the HelpBroker is used to display the
+     *		content.
+     * @param presentationName The name of a Presentation section to control 
+     *		the display of the content. Also for some Presenations this
+     *		will be used to "name" the Presentation.
+     * 
+     * @see getHelpKeyActionListener
+     * @see enableHelpKey(Component, String, HelpSet);
+     * @throws IllegalArgumentException if presentation != null and hs == null
+     */
+    public void enableHelpKey(Component comp, String id, HelpSet hs,
+			      String presentation, String presentationName) {
+	if (id == null) {
+	    throw new NullPointerException("id");
+	}
+	if (presentation != null && hs == null) {
+	    throw new IllegalArgumentException("hs");
+	}
+	CSH.setHelpIDString(comp, id);
+	if (hs !=null) {
+	    CSH.setHelpSet(comp, hs);
+	}
+	if (comp instanceof JComponent) {
+	    JComponent root = (JComponent) comp;
+	    ActionListener al = null;
+	    if (presentation == null) {
+		al = getDisplayHelpFromFocus();
+	    } else {
+		al = new CSH.DisplayHelpFromFocus(hs, presentation, 
+						  presentationName);
+	    }
+	    root.registerKeyboardAction(al,
+				   KeyStroke.getKeyStroke(KeyEvent.VK_HELP, 0),
+				   JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
+	    root.registerKeyboardAction(al,
+				    KeyStroke.getKeyStroke(KeyEvent.VK_F1, 0),
+				    JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
+	} else {
+	    helpKeyHS = hs;
+	    helpKeyPresentation = presentation;
+	    helpKeyPresentationName = presentationName;
+	    comp.addKeyListener(this);
+	}
+    }
+
+    /**
+     * Invoked when a key is typed. This event occurs when a
+     * key press is followed by a key release.  Not intended to be overridden or extended.
+     */
+    public void keyTyped(KeyEvent e) {
+	//ignore
+    }
+
+    /**
+     * Invoked when a key is pressed. Not intended to be overridden or extended.
+     */
+    public void keyPressed(KeyEvent e) {
+	//ingore
+    }
+
+
+
+    /**
+     * Invoked when a key is released.  Not intended to be overridden or extended.
+     */
+    public void keyReleased(KeyEvent e) {
+	// simulate what is done in JComponents registerKeyboardActions.
+	int code = e.getKeyCode();
+	if (code == KeyEvent.VK_F1 || code == KeyEvent.VK_HELP) {
+	    ActionListener al = null;
+	    if (helpKeyHS != null) {
+		al = new CSH.DisplayHelpFromFocus(helpKeyHS, 
+						  helpKeyPresentation,
+						  helpKeyPresentationName);
+	    } else {
+		al = getDisplayHelpFromFocus();
+	    }
+	    al.actionPerformed(new ActionEvent(e.getComponent(),
+					       ActionEvent.ACTION_PERFORMED,
+					       null));
+	}
+	
+    }
+
+    /**
+     * Enables help for a Component. This method sets a 
+     * component's helpID and HelpSet. 
+     *
+     * @param comp the Component to set the id and hs on.
+     * @param id the String value of an Map.ID.
+     * @param hs the HelpSet the id is in. If hs is null the default HelpSet
+     * will be assumed.
+     * @see CSH.setHelpID
+     * @see CSH.setHelpSet
+     */
+    public void enableHelp(Component comp, String id, HelpSet hs) 
+    {
+	if (id == null) {
+	    throw new NullPointerException("id");
+	}
+	CSH.setHelpIDString(comp, id);
+	if (hs != null) {
+	    CSH.setHelpSet(comp, hs);
+	}
+    }
+
+    /**
+     * Enables help for a MenuItem. This method sets a 
+     * component's helpID and HelpSet. 
+     *
+     * @param comp the MenuItem to set the id and hs on.
+     * @param id the String value of an Map.ID.
+     * @param hs the HelpSet the id is in. If hs is null the default HelpSet
+     * will be assumed.
+     * @see CSH.setHelpID
+     * @see CSH.setHelpSet
+     */
+    public void enableHelp(MenuItem comp, String id, HelpSet hs) 
+    {
+	if (id == null) {
+	    throw new NullPointerException("id");
+	}
+	CSH.setHelpIDString(comp, id);
+	if (hs != null) {
+	    CSH.setHelpSet(comp, hs);
+	}
+    }
+
+    /**
+     * Enables help for a Component. This method sets a 
+     * Component's helpID and HelpSet and adds an ActionListener. 
+     * When an action is performed
+     * it displays the Component's helpID and HelpSet in the default viewer.
+     *
+     * @param comp the Component to set the id and hs on. If the Component is not 
+     * a javax.swing.AbstractButton or a 
+     * java.awt.Button an IllegalArgumentException is thrown.
+     * @param id the String value of an Map.ID.
+     * @param hs the HelpSet the id is in. If hs is null the default HelpSet
+     * will be assumed.
+     *
+     * @see CSH.setHelpID
+     * @see CSH.setHelpSet
+     * @see javax.swing.AbstractButton
+     * @see java.awt.Button
+     * @throws IllegalArgumentException if comp is null.
+     */
+    public void enableHelpOnButton(Component comp, String id, HelpSet hs) 
+    {
+	if (!(comp instanceof AbstractButton) && !(comp instanceof Button)) {
+	    throw new IllegalArgumentException("Invalid Component");
+	}
+	if (id == null) {
+	    throw new NullPointerException("id");
+	}
+	CSH.setHelpIDString(comp, id);
+	if (hs != null) {
+	    CSH.setHelpSet(comp, hs);
+	}
+	if (comp instanceof AbstractButton) {
+	    AbstractButton button = (AbstractButton) comp;
+	    button.addActionListener(getDisplayHelpFromSource());
+	} else 	if (comp instanceof Button) {
+	    Button button = (Button) comp;
+	    button.addActionListener(getDisplayHelpFromSource());
+	}
+    }
+
+    /**
+     * Enables help for a MenuItem. This method sets a 
+     * Component's helpID and HelpSet and adds an ActionListener. 
+     * When an action is performed
+     * it displays the Component's helpID and HelpSet in the default viewer.
+     *
+     * @param comp the MenuItem to set the id and hs on. If comp is null
+     * an IllegalAgrumentException is thrown.
+     * @param id the String value of an Map.ID.
+     * @param hs the HelpSet the id is in. If hs is null the default HelpSet
+     * will be assumed.
+     * @see CSH.setHelpID
+     * @see CSH.setHelpSet
+     * @see java.awt.MenuItem
+     * @throws IllegalArgumentException if comp is null.
+     */
+    public void enableHelpOnButton(MenuItem comp, String id, HelpSet hs) 
+    {
+	if (comp == null) {
+	    throw new IllegalArgumentException("Invalid Component");
+	}
+	if (id == null) {
+	    throw new NullPointerException("id");
+	}
+	CSH.setHelpIDString(comp, id);
+	if (hs != null) {
+	    CSH.setHelpSet(comp, hs);
+	}
+	comp.addActionListener(getDisplayHelpFromSource());
+    }
+
+    /**
+     * Enables help for a Component. This method sets a 
+     * Component's helpID and HelpSet and adds an ActionListener. 
+     * When an action is performed
+     * it displays the Component's helpID and HelpSet in the default viewer.
+     *
+     * @param comp the Component to set the id and hs on. If the Component is not 
+     * a javax.swing.AbstractButton or a 
+     * java.awt.Button an IllegalArgumentException is thrown.
+     * @param id the String value of an Map.ID.
+     * @param hs the HelpSet the id is in. If hs is null the default HelpSet
+     * will be assumed.
+     *
+     * @see CSH.setHelpID
+     * @see CSH.setHelpSet
+     * @see javax.swing.AbstractButton
+     * @see java.awt.Button
+     * @throws IllegalArgumentException if comp is null.
+     */
+    public void enableHelpOnButton(Object obj, String id, HelpSet hs,
+				   String presentation, 
+				   String presentationName) 
+    {
+	if (!(obj instanceof AbstractButton) && !(obj instanceof Button) &&
+	       !(obj instanceof MenuItem)) {
+	    throw new IllegalArgumentException("Invalid Object");
+	}
+	if (id == null) {
+	    throw new NullPointerException("id");
+	}
+
+	if (obj instanceof AbstractButton || obj instanceof Button) {
+	    CSH.setHelpIDString((Component)obj, id);
+	    if (hs != null) {
+		CSH.setHelpSet((Component)obj, hs);
+	    }
+	} else {
+	    CSH.setHelpIDString((MenuItem)obj, id);
+	    if (hs != null) {
+		CSH.setHelpSet((MenuItem)obj, hs);
+	    }
+	}
+	    
+	if (presentation == null) {
+	    if (obj instanceof AbstractButton) {
+		AbstractButton button = (AbstractButton) obj;
+		button.addActionListener(getDisplayHelpFromSource());
+	    } else if (obj instanceof Button) {
+		Button button = (Button) obj;
+		button.addActionListener(getDisplayHelpFromSource());
+	    } else if (obj instanceof MenuItem) {
+		MenuItem item = (MenuItem) obj;
+		item.addActionListener(getDisplayHelpFromSource());
+	    }
+	} else {
+	    if (obj instanceof AbstractButton) {
+		AbstractButton button = (AbstractButton) obj;
+		button.addActionListener(new CSH.DisplayHelpFromSource(hs,
+								       presentation,
+								       presentationName));
+	    } else if (obj instanceof Button) {
+		Button button = (Button) obj;
+		button.addActionListener(new CSH.DisplayHelpFromSource(hs,
+								       presentation,
+								       presentationName));
+	    } else if (obj instanceof MenuItem) {
+		MenuItem item = (MenuItem) obj;
+		item.addActionListener(new CSH.DisplayHelpFromSource(hs,
+								     presentation,
+								     presentationName));
+	    }
+	}	    
+	    
+    }
+
+    /**
+     * Returns the default DisplayHelpFromFocus listener.
+     *
+     * @see enableHelpKey
+     */
+    protected ActionListener getDisplayHelpFromFocus() {
+	if (displayHelpFromFocus == null) {
+	    displayHelpFromFocus = new CSH.DisplayHelpFromFocus(this);
+	}
+	return displayHelpFromFocus;
+    }
+
+    /**
+     * Returns the default DisplayHelpFromSource listener.
+     *
+     * @see enableHelp
+     */
+    protected ActionListener getDisplayHelpFromSource() {
+	if (displayHelpFromSource==null) {
+	    displayHelpFromSource = new CSH.DisplayHelpFromSource(this);
+	}
+	return displayHelpFromSource;
+    }
+
+    /**
+     * Set the activation window from given Component or MenuItem. It find Window component
+     * in the component tree from given Component or MenuItem end call 
+     * <pre>setActivationWindow</pre>.
+     * @parem comp the activation Component or MenuItem
+     * @since 1.1
+     *
+     * @see setActivationWindow
+     */
+    public void setActivationObject(Object comp) {
+	mw.setActivationObject(comp);
+    }
+    
+    /**
+     * Set the activation window. If the window is an instance of a
+     * Dialog and the is modal, modallyActivated help is set to true and 
+     * ownerDialog is set to the window. In all other instances 
+     * modallyActivated is set to false and ownerDialog is set to null.
+     * @param window the activating window
+     * @since 1.1
+     */
+    public void setActivationWindow(Window window) {
+	mw.setActivationWindow(window);
+    }
+		    
+
+    // the listeners.
+    protected ActionListener displayHelpFromFocus;
+    protected ActionListener displayHelpFromSource;
+
+    /*
+     * Make sure the Look and Feel will be set
+     */
+    static {
+	SwingHelpUtilities.installLookAndFeelDefaults();
+    }
+
+    /**
+     * Debugging code...
+     */
+
+    private static final boolean debug = false;
+    private static void debug(Object msg) {
+	if (debug) {
+	    System.err.println("DefaultHelpBroker: "+msg);
+	}
+    }
+ 
+}
+
diff --git a/jhMaster/JavaHelp/src/new/javax/help/DefaultHelpHistoryModel.java b/jhMaster/JavaHelp/src/new/javax/help/DefaultHelpHistoryModel.java
new file mode 100644
index 0000000000000000000000000000000000000000..3078e19c910a7a181b028597529cfd3cbea27270
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/DefaultHelpHistoryModel.java
@@ -0,0 +1,393 @@
+/*
+ * @(#)DefaultHelpHistoryModel.java	1.4 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+
+package javax.help;
+
+import java.beans.*;
+import java.util.Vector;
+import javax.help.event.*;
+import javax.help.Map.ID;
+import java.util.Enumeration;
+import java.net.URL;
+import java.util.Stack;
+/**
+ * DefaultHelpHistoryModel is default implementation of HelpHistoryModel interface
+ *
+ * @author  Richard Gregor
+ * @version   1.4     10/30/06
+ */
+
+public class DefaultHelpHistoryModel implements HelpHistoryModel{
+    
+    protected Vector history = new Vector();
+    protected int historyIndex = -1;
+    protected HelpModel helpModel;
+    protected EventListenerList listenerList = new EventListenerList();
+    protected JHelp help;
+    
+    /** 
+     * Creates new DefaultHelpHistoryModel for given JHelp
+     *
+     * @param help The JHelp
+     */
+    public DefaultHelpHistoryModel(JHelp help) {
+        this.help = help;
+        if (help != null){
+            setHelpModel(help.getModel());            
+        }
+    }
+  
+    /**
+     * Sets a new HelpModel
+     *
+     * @param model The new HelpModel
+     */
+    public void setHelpModel(HelpModel model){
+        if(model == helpModel)
+            return;
+        else
+            discard();
+        if(helpModel != null)
+            helpModel.removeHelpModelListener(this);
+        if(model != null)
+            model.addHelpModelListener(this);
+         helpModel = model;        
+    }
+        
+            
+    /**
+     * Removes a listener previously added with <tt>addHelpHistoryModelListener</tt>
+     *
+     * @param l The listener to remove.
+     * @see javax.help.HelpHistoryModel#addHelpHistoryModelListener
+     */
+    public void removeHelpHistoryModelListener(HelpHistoryModelListener l) {
+        listenerList.remove(HelpHistoryModelListener.class, l);
+    }
+    
+    /**
+     * Adds a listener for the HelpHistoryModelEvent posted after the model has
+     * changed.
+     *
+     * @param l The listener to add.
+     * @see javax.help.HelpHistoryModel#removeHelpHistoryModelListener
+     */
+    public void addHelpHistoryModelListener(HelpHistoryModelListener l) {
+        listenerList.add(HelpHistoryModelListener.class, l);
+    }
+    
+    /**
+     * Discards a history
+     */
+    public void discard() {
+        history.setSize(0);
+        historyIndex = -1;
+        fireHistoryChanged(this,false,false);
+    }
+    
+    /**
+     * Returns a history
+     *
+     * @return The vector of history entries
+     */
+    public Vector getHistory(){
+        return history;
+    }
+    
+    /**
+     * Removes the last history entry
+     *
+     */
+    public void removeLastEntry(){
+        int size = history.size();
+        if(size > 0)
+            history.removeElementAt(history.size() -1);
+    }
+    /**
+     * Returns a current history position
+     *
+     * @return The history index
+     */
+    public int getIndex(){
+        return historyIndex;
+    }
+    
+    /**
+     * Sets the next history entry
+     */
+    public void goForward(){
+        setHistoryEntry(historyIndex+1);
+    }
+    
+    /**
+     * Sets the previous histroy entry
+     */
+    public void goBack(){
+        setHistoryEntry(historyIndex-1);
+    }
+    
+    /**
+     * Returns a forward history vector
+     *
+     * @return The vector of forward history entries
+     */
+    public Vector getForwardHistory() {
+        Vector historyCopy = (Vector)history.clone();
+        Vector forwardHistory = new Vector();
+        int size = historyCopy.size();
+        debug(" forward size : "+size);
+        for(int i = historyIndex + 1 ; i < size; i++){
+            forwardHistory.addElement(historyCopy.elementAt(i)); 
+        }
+        return forwardHistory;
+    }
+    
+    /**
+     * Returns a backward history vector
+     *
+     * @return The vector of backward history entries
+     */
+    public Vector getBackwardHistory() {        
+        Vector backwardHistory = new Vector();
+        Vector historyCopy = (Vector)history.clone();
+        debug(" backward size : "+historyCopy.size());
+        debug(" backward index : "+historyIndex);
+        if(historyCopy != null){
+            for(int i = 0 ; i < historyIndex; i++){            
+                backwardHistory.addElement(historyCopy.elementAt(i));
+            }
+        }
+        
+        return backwardHistory;        
+    }
+    
+    /**
+     * Sets the current history entry
+     *
+     * @param index The index of history entry
+     */
+    public void setHistoryEntry(int index) {
+        debug("setHistoryEntry("+index+")");
+        
+        
+        if (helpModel == null) {
+            return;
+        }
+        
+        if (index < 0 || index >= history.size()) {
+            // invalid index
+            discard();
+            return;
+        }
+        
+        HelpModelEvent e = (HelpModelEvent) history.elementAt(index);
+        // set the historyIndex so it is ready to take the next event...
+        historyIndex = index-1;
+        ID id = e.getID();
+        URL url = e.getURL();
+        JHelpNavigator navigator = e.getNavigator();
+        if (id != null) {
+            // try to set the ID
+            try {
+                debug("  setCurrentID"+id);
+                helpModel.setCurrentID(id, e.getHistoryName(),e.getNavigator());
+                if(navigator != null)
+                    help.setCurrentNavigator(navigator);
+                return;
+            } catch (Exception ex) {
+                // fall through
+            }
+        }
+        if (url != null) {
+            // try to set the URL
+            try {
+                debug("  setCurrentURL"+url);
+                helpModel.setCurrentURL(url,e.getHistoryName(),e.getNavigator());
+                if(navigator != null)
+                    help.setCurrentNavigator(navigator);                    
+                return;
+            } catch (Exception ex) {
+                // fall through
+            }
+        }       
+            
+        // this really should not happen but...
+        discard();    
+    }
+    /**
+     * Fires the history change
+     */
+    protected void fireHistoryChanged(Object source, boolean previous, boolean next) {
+	Object[] listeners = listenerList.getListenerList();
+	HelpHistoryModelEvent e = null;
+
+	for (int i = listeners.length - 2; i >= 0; i -= 2) {
+	    if (listeners[i] == HelpHistoryModelListener.class) {
+		if (e == null) {
+		    e = new HelpHistoryModelEvent(source, previous, next);
+		}
+		debug("fireHistoryChanged: ");
+		debug("  "+listeners[i+1]);
+		debug("  previous="+e.isPrevious() + " next="+e.isNext());
+		((HelpHistoryModelListener)listeners[i+1]).historyChanged(e);
+	    }	       
+	}
+    }
+    
+    
+    /**
+     * Tells the listener that the current ID in the HelpModel has
+     * changed.
+     * All highlights from the previous location change at this point.
+     *
+     * @param e The event
+     */
+    public void idChanged(HelpModelEvent e) {
+        debug("idChanged("+e+")");
+        debug("  historyIndex=="+historyIndex);
+        debug("  history.size=="+history.size());
+        
+        if (historyIndex == history.size()-1) {
+            // we are at the end
+            // (this covers the initial case of historyIndex == -1
+            history.addElement(e);
+            historyIndex += 1;
+            fireHistoryChanged(this,(historyIndex > 0),(historyIndex < history.size()-1));           
+            return;
+        }
+        
+        if (historyIndex >= -1 &&
+        historyIndex < history.size()-1) {
+            // check the next slot where to record
+            
+            historyIndex += 1;	// advance
+            HelpModelEvent h
+            = (HelpModelEvent) history.elementAt(historyIndex);
+            
+            if (h == null) {
+                // this really should not happen
+                discard();
+                return;
+            }
+            
+            // compare ID's first
+            if (h.getID() != null &&	e.getID() != null &&
+            h.getID().equals(e.getID())) {
+                // we are were we wanted to be, just return
+                fireHistoryChanged(this,(historyIndex > 0),(historyIndex < history.size()-1));
+                return;
+            }
+            
+            // compare URL's now
+            if (h.getURL() != null && e.getURL() != null &&
+            h.getURL().sameFile(e.getURL())) {
+                // we are were we wanted to be, just return
+                fireHistoryChanged(this,(historyIndex > 0),(historyIndex < history.size()-1));
+                return;
+            }
+            
+            // new location is different, so throw away object and the rest
+            history.setSize(historyIndex);
+            // add the new element
+            history.addElement(e);
+            fireHistoryChanged(this,(historyIndex > 0),(historyIndex < history.size()-1));
+        }
+    }
+    
+    /**
+     * Removes entries related to removed HelpSet from history
+     *
+     * @param hs The removed HelpSet
+     */
+    public void removeHelpSet(HelpSet hs){
+        Enumeration e = history.elements();
+        debug(" size before " +history.size());
+        
+        if(debug){
+            System.err.println("before : ");
+            for(int j = 0; j < history.size(); j++){
+                System.err.println(((HelpModelEvent)history.elementAt(j)).getID());
+            }
+        }
+        int size = history.size();
+        Vector newHistory = new Vector();
+        int index = historyIndex;
+        
+        for(int i = 0; i < size; i++){
+            HelpModelEvent evt = (HelpModelEvent)history.elementAt(i);
+            ID id = evt.getID();
+            debug(" update id "+id);
+            URL url = evt.getURL();
+            debug(" update url " +url);
+            if ((id != null) && (id.hs != hs)) {
+                debug(" remain - "+id);
+                newHistory.addElement(history.elementAt(i));
+            }
+            else if (url != null) {
+                //find out if there is a matching ID for this URL
+                ID idcan = hs.getCombinedMap().getIDFromURL(url);
+                if(idcan == null){
+                    debug(" remain > "+idcan);
+                    newHistory.addElement(history.elementAt(i));
+                }
+            }
+        }
+        
+        history = newHistory;
+        historyIndex = history.size() -1;
+        
+        debug(" size after " + history.size());
+        if(debug){
+            System.err.println("after : ");
+            for(int j = 0; j < history.size(); j++){
+                System.err.println(((HelpModelEvent)history.elementAt(j)).getID());
+            }
+        }
+        setHistoryEntry(historyIndex);
+        //computeHistoryButtons();
+        
+    }   
+
+    /**
+     * Returns HelpModel
+     *
+     * @return The HelpModel
+     */
+    protected HelpModel getModel(){
+        return helpModel;
+    }
+    /**
+     * For printf debugging.
+     */
+    private static boolean debug = false;
+    private static void debug(String str) {
+        if (debug) {
+            System.out.println("BasicHelpUI: " + str);
+        }
+    }    
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/DefaultHelpModel.java b/jhMaster/JavaHelp/src/new/javax/help/DefaultHelpModel.java
new file mode 100644
index 0000000000000000000000000000000000000000..14cd059dd7db6c0120b6a198afbea382568effd8
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/DefaultHelpModel.java
@@ -0,0 +1,510 @@
+/*
+ * @(#)DefaultHelpModel.java	1.49 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help;
+
+import java.net.URL;
+import java.util.Vector;
+import java.util.Enumeration;
+import java.io.Serializable;
+import javax.help.event.EventListenerList;
+import javax.help.event.*;
+import javax.help.Map.ID;
+import javax.help.TextHelpModel.Highlight;
+import java.beans.*;
+
+/**
+ * This class implements the javax.help.HelpModel API and 
+ * notifies the JHelpModel listeners when changes occur.
+ *
+ * @author Roger D. Brinkley
+ * @author Eduardo Pelegri-Llopart
+ * @@version   1.49     10/30/06
+ */
+
+public class DefaultHelpModel implements TextHelpModel, Serializable {
+    private HelpSet helpset;		// the loaded, aka "the top", HelpSet
+    private ID currentID;
+    private URL currentURL;
+    private String navID;	// the label to the "current" navigator
+    private Vector highlights = new Vector();
+
+    private String title;	// title of the document - if appropriate
+
+    protected EventListenerList listenerList = new EventListenerList();
+    protected EventListenerList textListenerList = new EventListenerList();   protected PropertyChangeSupport changes = new PropertyChangeSupport(this);
+
+    /**
+     * Constructs a HelpModel from a HelpSet
+     *
+     * @see javax.help.HelpSet
+     * @param hs The HelpSet from which to build this model. A null hs is valid
+     * creating a DefaultHelpModel without a HelpSet.
+     */
+    public DefaultHelpModel(HelpSet hs) {
+	this.helpset = hs;
+    }
+
+    /**
+     * Sets the HelpSet for this HelpModel. A null hs is valid.
+     */
+    public void setHelpSet(HelpSet hs) {
+	HelpSet old = this.helpset;
+	this.helpset = hs;
+	changes.firePropertyChange("helpSet", old, hs);
+    }
+
+    /**
+     * Gets the backing HelpSet.
+     *
+     * @return the helpset. A null hs is valid.
+     */
+    public HelpSet getHelpSet() {
+	return helpset;
+    }
+
+    /**
+     * Sets the current ID.
+     * HelpModelListeners and HelpVisitListeners are notified.
+     * If the parameter ident is null, the homeID of the current HelpSet is
+     * used unless it is also null in which case the method returns without
+     * setting the currentID.
+     *
+     * @param ident The ID to set. 
+     * If ident is null set the currentID to the HelpSet's HomeID.
+     * If the HomeID doesn't exist the currentID is set to null.
+     * @exception InvalidHelpSetContextException The ID is not valid for the HelpSet
+     */
+    public void setCurrentID(ID ident) throws InvalidHelpSetContextException {
+        setCurrentID(ident,(String)null, (JHelpNavigator) null);
+
+    }
+    /**
+     * Sets the current ID relative to some HelpSet
+     * HelpModelListeners and HelpVisitListeners are notified
+     *
+     * @param id the ID used to set
+     * @param historyName the name for history storage
+     * @param navigator the name of the navigator for history
+     * @exception InvalidHelpSetContextException The HelpSet of the ID is not
+     * valid for the HelpSet currently loaded in the model
+     */
+    public void setCurrentID(ID ident, String historyName, JHelpNavigator navigator) throws InvalidHelpSetContextException{
+        if (ident == null) {
+	    ident = helpset.getHomeID();
+	}
+	if (ident == null || ident.equals(currentID)) {
+	    // quick return if already set
+	    return;
+	}
+	
+	String id = ident.id;
+	HelpSet hs = ident.hs;
+
+	if (! helpset.contains(hs)) {
+	    // invalid context
+	    throw new InvalidHelpSetContextException("Wrong context",
+						     helpset,
+						     hs);
+	}
+
+	Map map = helpset.getCombinedMap();
+	currentID = ident;
+	try {
+	    ID tmpID = ident;
+	    URL url;
+	    if (hs == helpset) { 
+		url = map.getURLFromID(ident);
+	    } else {
+		Map hsmap = hs.getLocalMap();
+		url = hsmap.getURLFromID(ident);
+	    }
+	    if (currentURL != null &&
+		currentURL.equals(url)) {
+		// workaround bug in 1.1.x doesn't compare anchors correctly
+		String currentRef = currentURL.getRef();
+		String urlRef = url.getRef();
+		// if both are null then they are the same
+		if (currentRef == null && urlRef == null) {
+		    return;	// avoid loops, don't propagate the ID change!
+		}
+		// if both have some value and have the same content they are
+		// the same
+		if (currentRef != null && urlRef != null &&
+		    currentRef.compareTo(urlRef) == 0) {
+		    return;	// avoid loops, don't propagate the ID change!
+		}
+	    }
+	    currentURL = url;
+	} catch (Exception ex) {
+	    currentURL = null;
+	}
+        
+        // remove the highlights, but no need to fire an event because it is
+	// implicit in the next fireIDChanged() event
+	highlights.setSize(0);
+	fireIDChanged(this, currentID, currentURL, historyName, navigator);
+    }
+    
+
+    /**
+     * Gets the current ID.
+     *
+     * @return the current ID. A null ID is a valid id. If no ID has been set
+     * a null ID is returned.
+     */
+    public ID getCurrentID() {
+	return currentID;
+    }
+        
+    /**
+     * Sets the current URL.
+     * The current ID changes if there is a matching ID for this URL
+     * and HelpModelListners are notified.
+     *
+     * @param url The url to set the model to. A null URL is a valid url.
+     */
+    public void setCurrentURL(URL url) {
+        setCurrentURL(url, (String)null, (JHelpNavigator)null);        
+    }
+
+    /**
+     * Sets the current URL and the name wich will appear in history list.
+     * HelpModelListeners are notified.
+     * The current ID changes if there is a matching id for this URL
+     *
+     * @param url The URL to set.
+     * @param historyName The name to set for history
+     * @param navigator The name of the navigator for history
+     */
+    public void setCurrentURL(URL url, String historyName, JHelpNavigator navigator){
+        
+        boolean fire = false;
+
+        // Setup CurrentURL
+        if (currentURL == null) {
+            if (currentURL != url) {
+		currentURL = url;
+                fire = true;
+            }
+        } else {
+            if (!currentURL.equals(url)) {
+                currentURL = url;
+                fire = true;
+            }
+        }
+
+        // Setup CurrentID
+        if (currentURL == null) {
+            if (currentID != null) {
+                currentID = null;
+                fire = true;
+            }
+        } else {
+            ID id = helpset.getCombinedMap().getIDFromURL(currentURL);
+            if (currentID == null) {
+                if (currentID != id) {
+                    currentID = id;
+                    fire = true;
+                }
+            } else {
+                if (!currentID.equals(id)) {
+                    currentID = id;
+                    fire = true;
+                }
+            }
+        }
+
+        // Fire only if CurrentURL or CurrentID was changed
+        if (fire) {        
+	    // remove the highlights, but no need to fire an event because it is
+	    // implicit in the next fireIDChanged() event
+	    highlights.setSize(0);
+	    fireIDChanged(this, currentID, currentURL, historyName, navigator);
+        }
+    }
+    
+    
+    /**
+     * Returns the current URL
+     *
+     * @return The current URL. A null URL is a valid URL. If no URL has been
+     * previously set a null URL will be returned.
+     */
+    public URL getCurrentURL() {
+	return currentURL;
+    }
+
+    /**
+     * Highlights a range of positions in a document.
+     *
+     * @param pos0 start position
+     * @param pos1 end position
+     */
+    public void addHighlight(int pos0, int pos1) {
+	debug("addHighlight("+pos0+", "+pos1+")");
+	highlights.addElement(new DefaultHighlight(pos0, pos1));
+	fireHighlightsChanged(this);
+    }
+
+    /**
+     * Removes highlights.
+     */
+    public void removeAllHighlights() {
+	debug("removeAllHighlights");
+	highlights.setSize(0);
+	fireHighlightsChanged(this);
+    }
+	
+    /**
+     * Set highlights. Clear the current Hightlights and set new Highlights
+     * 
+     * @param h An array of Hightlights. If h is null it is the same as setting 
+     * no highlights
+     */
+    public void setHighlights(Highlight[] h) {
+	highlights.setSize(0);
+	if (h == null) {
+	    return;
+	}
+	for (int i=0; i<h.length; i++) {
+	    highlights.addElement(new DefaultHighlight(h[i].getStartOffset(),
+						       h[i].getEndOffset()));
+	}
+	if (highlights.size() > 0) {
+	    fireHighlightsChanged(this);
+	}
+    }
+
+    /**
+     * Geta all the highlights currently active.
+     *
+     * @return An array of highlights
+     */
+    public Highlight[] getHighlights() {
+	Highlight back[] = new DefaultHighlight[highlights.size()];
+	highlights.copyInto(back);
+	return back;
+    }
+
+
+    /**
+     * Adds a listener for the HelpModelEvent posted after the model has
+     * changed.
+     * 
+     * @param l - The listener to add.
+     * @see javax.help.HelpModel#removeHelpModelListener
+     * @throws IllegalArgumentException if l is null.
+     */
+    public void addHelpModelListener(HelpModelListener l) {
+	debug("addHelpModelListener: ");
+	debug("  l:"+l);
+	if (debug) {
+	    try {
+		throw new Exception("");
+	    } catch (Exception ex) {
+		ex.printStackTrace();
+	    }
+	}
+	listenerList.add(HelpModelListener.class, l);
+    }
+
+    /**
+     * Removes a listener previously added with <b>addHelpListener</b>
+     *
+     * @param l - The listener to remove. If l is not in the list of listeners
+     * it is ignored.
+     * @see javax.help.HelpModel#addHelpModelListener
+     * @throws IllegalArgumentException if l is null.
+     */
+    public void removeHelpModelListener(HelpModelListener l) {
+	listenerList.remove(HelpModelListener.class, l);
+    }
+
+    /**
+     * Adds a listener for the TextHelpModelEvent posted after the model has
+     * changed.
+     * 
+     * @param l - The listener to add.
+     * @see javax.help.HelpModel#removeHelpModelListener
+     * @throws IllegalArgumentException if l is null.
+     */
+    public void addTextHelpModelListener(TextHelpModelListener l) {
+	debug("addTextHelpModelListener: ");
+	debug("  l:"+l);
+	// HERE
+	if (debug) {
+	    try {
+		throw new Exception("");
+	    } catch (Exception ex) {
+		ex.printStackTrace();
+	    }
+	}
+	textListenerList.add(TextHelpModelListener.class, l);
+    }
+
+    /**
+     * Removes a listener previously added with <b>addHelpListener</b>
+     *
+     * @param l - The listener to remove. If l is not on the list of listeners
+     * it is ignored.
+     * @see javax.help.HelpModel#addHelpModelListener
+     * @throws IllegalArgumentException if l is null.
+     */
+    public void removeTextHelpModelListener(TextHelpModelListener l) {
+	textListenerList.remove(TextHelpModelListener.class, l);
+    }
+
+    /**
+     * Adds a listener to changes to the properties in this model.
+     *
+     * @param l  the listener to add
+     */
+    public void addPropertyChangeListener(PropertyChangeListener l) {
+	changes.addPropertyChangeListener(l);
+    }
+
+    /**
+     * Removes a listener to changes to the properties in this model.
+     *
+     * @param l  the listener to remove. If l is not on the list of listeners
+     * it is ignored.
+     */
+    public void removePropertyChangeListener(PropertyChangeListener l) {
+	changes.removePropertyChangeListener(l);
+    }
+
+    /**
+     * Assigns the document title.
+     *
+     * @param title the Title for the document currently being shown. A null 
+     * title is valid.
+     */
+    public void setDocumentTitle(String title) {
+	String oldTitle = this.title;
+	this.title = title;
+	changes.firePropertyChange("documentTitle", oldTitle, title);
+    }
+
+    /**
+     * Gets the document title.
+     *
+     * @return The title for the current document. A null title is valid. If 
+     * the title has not be previously set it will be null.
+     */
+    public String getDocumentTitle() {
+	return title;
+    }
+
+    protected void fireIDChanged(Object source, ID id, URL url, String historyName, JHelpNavigator navigator) {
+	Object[] listeners = listenerList.getListenerList();
+	HelpModelEvent e = null;
+
+	for (int i = listeners.length - 2; i >= 0; i -= 2) {
+	    if (listeners[i] == HelpModelListener.class) {
+		if (e == null) {
+		    e = new HelpModelEvent(source, id, url, historyName, navigator);
+		}
+		debug("fireIDChanged: ");
+		debug("  "+listeners[i+1]);
+		debug("  id="+e.getID() + " url="+e.getURL());
+		((HelpModelListener)listeners[i+1]).idChanged(e);
+	    }	       
+	}
+    }
+
+    protected void fireIDChanged(Object source, ID id, URL url){
+        fireIDChanged(source, id, url, (String)null, (JHelpNavigator)null);
+    }
+    
+    protected void fireHighlightsChanged(Object source) {
+	Object[] listeners = textListenerList.getListenerList();
+	TextHelpModelEvent e = null;
+
+	for (int i = listeners.length - 2; i >= 0; i -= 2) {
+	    if (listeners[i] == TextHelpModelListener.class) {
+		if (e == null) {
+		    e = new TextHelpModelEvent(source);
+		}
+		debug("fireHighlightsChanged: ");
+		debug("  "+listeners[i+1]);
+		debug("  "+e);
+		((TextHelpModelListener)listeners[i+1]).highlightsChanged(e);
+	    }	       
+	}
+    }
+
+    /**
+     * A default implementation of TextHelpModel.Highlight
+     */
+
+    public static class DefaultHighlight implements Highlight {
+	public int start, end;	// start, end offsets.  >=0
+
+	/**
+	 * Constructor
+	 */
+	public DefaultHighlight(int start, int end) {
+	    if (start < 0) {
+		throw new IllegalArgumentException("start");
+	    }
+	    if (end < 0) {
+		throw new IllegalArgumentException("end");
+	    }
+	    this.start = start;
+	    this.end = end;
+	}
+
+	/**
+	 * Start offset
+	 *
+	 * @returns start offset (>=0)
+	 */
+	public int getStartOffset() {
+	    return start;
+	}
+
+	/**
+	 * End offset
+	 *
+	 * @returns end offset (>=0)
+	 */
+	public int getEndOffset() {
+	    return end;
+	}
+    }
+
+    /**
+     * For printf debugging...
+     */
+    private static boolean debug = false;
+    private static void debug(String str) {
+        if (debug) {
+            System.err.println("DefaultHelpModel: " + str);
+        }
+    }
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/FavoritesAction.java b/jhMaster/JavaHelp/src/new/javax/help/FavoritesAction.java
new file mode 100644
index 0000000000000000000000000000000000000000..c32ad8ce3ada6dd083e7f8720b433c7702c97635
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/FavoritesAction.java
@@ -0,0 +1,80 @@
+/*
+ * @(#)FavoritesAction.java	1.3 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help;
+
+import java.awt.event.ActionListener;
+import java.util.Enumeration;
+import java.util.Locale;
+import javax.swing.UIManager;
+
+/**
+ *
+ * @author Roger Brinkley
+ * @version   1.3     10/30/06
+ */
+public class FavoritesAction extends AbstractHelpAction implements ActionListener {
+    
+    private static final String NAME = "FavoritesAction";
+    private JHelpFavoritesNavigator favorites=null;
+    private ActionListener favoritesActionListener=null;
+
+    /** Creates new FavoritesAction */
+    public FavoritesAction(Object control) {
+        super(control, NAME);
+        if (control instanceof JHelp) {
+            JHelp help = (JHelp)control;
+	    for (Enumeration e = help.getHelpNavigators(); e.hasMoreElements();) {
+		JHelpNavigator nav = (JHelpNavigator)e.nextElement();
+		if(nav instanceof JHelpFavoritesNavigator) {
+		    favorites = (JHelpFavoritesNavigator)nav;
+		    favoritesActionListener = favorites.getAddAction();
+		}
+	    }
+            
+            setEnabled(favoritesActionListener != null);
+            
+            putValue("icon", UIManager.getIcon(NAME + ".icon"));
+            
+	    Locale locale = null;
+	    try {
+		locale = help.getModel().getHelpSet().getLocale();
+	    } catch (NullPointerException npe) {
+		locale = Locale.getDefault();
+	    }
+            putValue("tooltip", HelpUtilities.getString(locale, "tooltip." + NAME));
+            putValue("access", HelpUtilities.getString(locale, "access." + NAME));
+        }
+    }
+
+    public void actionPerformed(java.awt.event.ActionEvent event) {
+	if (favoritesActionListener != null) {
+	    favoritesActionListener.actionPerformed(event);
+	}
+    }
+
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/FavoritesItem.java b/jhMaster/JavaHelp/src/new/javax/help/FavoritesItem.java
new file mode 100644
index 0000000000000000000000000000000000000000..f4804ac6df24cc051660e67036ea50f21989e407
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/FavoritesItem.java
@@ -0,0 +1,250 @@
+/*
+ * @(#)FavoritesItem.java	1.6 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help;
+
+import java.util.Vector;
+import java.util.Locale;
+import javax.help.Map.ID;
+import java.awt.datatransfer.*;
+import java.io.IOException;
+import java.io.Serializable;
+import java.net.URL;
+import java.net.MalformedURLException;
+
+/**
+ * A class for individual favorites items.
+ *
+ * @author Richard Gregor
+ * @version   1.6     10/30/06
+ */
+
+public class FavoritesItem extends TreeItem implements Transferable, Serializable{
+    private boolean isFolder = false;
+    
+    final public static DataFlavor FAVORITES_FLAVOR =
+    new DataFlavor(FavoritesItem.class, "Favorites Item");
+    
+    static DataFlavor flavors[] = {FAVORITES_FLAVOR };
+    
+    private FavoritesItem parent = null;
+    private Vector children = new Vector();
+    private String url= null;
+    private String target = null;
+    private String title = null;
+    //determines wheter item was initialized as empty or not
+    private boolean emptyInitState = true;   
+    private boolean visible = true;
+
+    /**
+     * Creates item with name
+     *
+     * @param name The name of item
+     */
+    public FavoritesItem(String name){     
+	setName(name);
+    }
+    
+    /**
+     * Creates empty item
+     */
+    public FavoritesItem(){
+        this(null);
+    }
+    /**
+     * Creates FavoritesItem.
+     *
+     * @param name The name of item
+     * @param target The target of item
+     * @param url The external representation of url
+     * @param title The title of the HelpSet
+     * @param locale The Locale of this item
+     */
+    public FavoritesItem(String name, String target, String url, String title, Locale locale){
+        this(name);
+        this.target = target;
+        this.url = url;
+        this.locale = locale;
+        this.title = title;
+    }
+    
+    public void setVisible(boolean visible){
+        this.visible = visible;
+    }
+
+    public boolean isVisible(){
+        return visible;
+    }
+
+    /**
+     * Returns the id for this item.
+     */
+    public String getTarget() {
+        return target;
+    }
+
+    /**
+     *Returns the external representation of url for this item.
+     */
+    public String getURLSpec(){
+        return url;
+    }    
+
+    /**
+     * Return the URL for this item
+     */
+    public URL getURL () {
+	try {
+	    return new URL(url);
+	} catch (MalformedURLException e) {
+	}
+	return null;
+    }
+	
+    /**
+     * Returns the title of HelpSet
+     */
+    public String getHelpSetTitle(){
+        return title;
+    }
+
+    /**
+     * Sets this item as folder.
+     */
+    public void setAsFolder(){
+        isFolder = true;
+    }
+
+    /**
+     * Returns wheter item allows children or not
+     */
+    public boolean allowsChildren(){
+        return isFolder();
+    }
+    
+    /**
+     * Returns whether or not this item is leaf
+     */
+    public boolean isLeaf(){
+        return(!isFolder());
+    }
+    /**
+     * Returns whether or not this item is folder.
+     */
+    public boolean isFolder(){
+        return isFolder;
+    }
+    
+    /**
+     * Adds FavoritesItem as a child.
+     *
+     * @param item The FavoritesItem.
+     */
+    public void add(FavoritesItem item) {
+        item.setParent(this);
+        children.add(item);
+        emptyInitState = false;
+        isFolder = true;
+    }
+    
+    /**
+     * Returns true if item was initialized as empty
+     */
+    public boolean emptyInitState(){
+        return emptyInitState;
+    }
+    
+    /**
+     * Removes FavoritesItem from vector of children.
+     *
+     * @param item The FavoritesItem to remove.
+     */
+    public void remove(FavoritesItem item) {
+        item.setParent(null);
+        children.remove(item);
+    }
+
+    /**
+     * Returns parent of FavoritesItem.
+     */
+    public FavoritesItem getParent() {
+        return parent;
+    }
+    
+    /**
+     * Sets the parent of this item.
+     *
+     * @param parent The FavoritesItem.
+     */
+    public void setParent(FavoritesItem parent) {
+        this.parent = parent;
+    }
+    
+    /**
+     * Returns children of this FavoritesItem.
+     */
+    public Vector getChildren() {
+        return children;
+    }
+    
+    public Object clone(){
+        FavoritesItem item = new FavoritesItem(getName(), target, url, 
+					       title, locale);
+        return item;
+    }
+    
+    public String toString(){
+        return getName();
+    }
+        
+    /**
+     * Returns an object which represents the data to be transferred.
+     */
+    public Object getTransferData(DataFlavor df) throws UnsupportedFlavorException, IOException {
+        if (df.equals(FAVORITES_FLAVOR)) {
+            return this;
+        }
+        else throw new UnsupportedFlavorException(df);
+    }
+    
+    /**
+     * Returns an array of DataFlavor objects indicating the flavors the data can be provided in.
+     */
+    public DataFlavor[] getTransferDataFlavors() {
+        return flavors;
+    }
+    
+    /**
+     * Returns whether or not the specified data flavor is supported for this object.
+     */
+    public boolean isDataFlavorSupported(DataFlavor df) {
+        return df.equals(FAVORITES_FLAVOR);
+    }
+    
+}
+
+
diff --git a/jhMaster/JavaHelp/src/new/javax/help/FavoritesNode.java b/jhMaster/JavaHelp/src/new/javax/help/FavoritesNode.java
new file mode 100644
index 0000000000000000000000000000000000000000..56302c6c1735cbf9b45359d0b014e188e30b4f44
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/FavoritesNode.java
@@ -0,0 +1,280 @@
+/*
+ * @(#)FavoritesNode.java	1.5 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help;
+
+import javax.swing.tree.*;
+import java.beans.*;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.IOException;
+import java.util.Enumeration;
+import java.io.ObjectOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+
+/**
+ * A class for Favorites node. This class forces none-folders to have children.
+ *
+ * @author Richard Gregor
+ * @version   1.5     10/30/06
+ */
+
+public class FavoritesNode extends DefaultMutableTreeNode  {
+    /**
+     * Header part of xml file
+     */
+    public static final String HEADER="<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"+
+    "<!DOCTYPE favorites\n PUBLIC \""+FavoritesView.publicIDString+
+    "\"\n        \"http://java.sun.com/products/javahelp/favorites_2_0.dtd\">\n"+
+    "\n<favorites version=\"2.0\">\n";
+    
+    /**
+     * XML element name
+     */
+    public static final String ELEMENT="favoriteitem";
+    /**
+     * Footer of xml document
+     */
+    public static final String FOOTER="</favorites>";
+    /**
+     * FavoritesItem userObject of this node
+     */
+    private FavoritesItem item;   
+    /**
+     * Creates a FavoritesNode for FavoritesItem.
+     *
+     * @param item The FavoritesItem
+     */
+    public FavoritesNode(FavoritesItem item) {
+        super(item);
+        this.item = item;
+    }
+    
+    /**
+     * Returns wheter node is allowed to have children or not.
+     */
+    public boolean getAllowsChildren() {
+        return ((FavoritesItem) getUserObject()).isFolder();
+    }
+    
+    /**
+     * Adds the child node.
+     *
+     * @param child The DefaultMutableTreeNode with FavoritesItem as UserObject.
+     */
+    public void add(DefaultMutableTreeNode child) {
+        super.add(child);
+        FavoritesItem childItem = (FavoritesItem) child.getUserObject();
+        FavoritesItem oldParent = childItem.getParent();
+        FavoritesItem newParent = (FavoritesItem) getUserObject();
+        newParent.add(childItem);        
+    }
+    
+    /**
+     * Removes the child node.
+     *
+     * @param child Node to remove.
+     */
+    public void remove(DefaultMutableTreeNode child) {
+        super.remove(child);
+        FavoritesItem childItem = (FavoritesItem) ((FavoritesNode) child).getUserObject();
+        FavoritesItem ParentItem = (FavoritesItem) getUserObject();
+        if (parent != null)
+            ParentItem.remove(childItem);
+    }
+    /**
+     * Returns the number of visible children
+     *
+     */
+    public int getVisibleChildCount(){
+        int count = 0;
+        if( item == null)
+            return 0;
+        
+        for(Enumeration en = item.getChildren().elements(); en.hasMoreElements();){
+            FavoritesItem nItem =(FavoritesItem)en.nextElement();
+            if(nItem.isVisible())
+                count++;
+        }
+        return count;
+    }
+    /**
+     * Returns the string representation of offset.
+     */
+    public String getOffset(){
+        String parentOffset = null;
+        String offset = null;
+        
+        FavoritesNode parent = (FavoritesNode)getParent();
+        if(parent != null){
+            parentOffset = parent.getOffset();
+            offset = parentOffset + "  ";
+        }else
+            offset = "  ";
+        
+        return offset;
+    }
+    /**
+     * Exports nodes descendants to the OutputStream
+     *
+     * @param out The OutputStream
+     */
+    public void export(OutputStream out) throws IOException{        
+        OutputStreamWriter writer = new OutputStreamWriter(out);
+        writer = exportHeader(out);
+        //exportNode(writer);
+        Enumeration chldn = children(); 
+        if(!(chldn.equals(DefaultMutableTreeNode.EMPTY_ENUMERATION))){
+            while(chldn.hasMoreElements()){
+                FavoritesNode node = (FavoritesNode)chldn.nextElement();
+                node.exportNode(writer);
+            }
+        }
+        writer.write(FOOTER);
+        //out.close();
+        writer.close();
+    }
+
+    /**
+     * Exports node and its descendants to the xml file according favorites.dtd.
+     *
+     * @param out The OutputStream
+     */
+    public void exportNode(OutputStreamWriter writer) throws IOException{
+        TreeNode paren = getParent();        
+        FavoritesItem item = (FavoritesItem)getUserObject();        
+        writer.write(getOffset()+"<"+getXMLElement()+ " text=\""+item.getName()+"\" ");
+        String target = item.getTarget();
+        if(target != null)
+            writer.write("target=\""+target+"\" ");
+        String url = item.getURLSpec();
+        if(url != null)
+            writer.write("url=\""+url+"\"");
+        String hstitle = item.getHelpSetTitle();
+        if(hstitle != null)
+            writer.write(" hstitle=\""+hstitle+"\"");
+        Enumeration chldn = children(); 
+        if(chldn.equals(DefaultMutableTreeNode.EMPTY_ENUMERATION))
+            writer.write("/>\n");
+        else{ 
+            writer.write(">\n");
+            Enumeration offspring = children.elements();
+            while(offspring.hasMoreElements()){
+                FavoritesNode off = (FavoritesNode)offspring.nextElement();
+                debug("offspring: "+off);
+                off.exportNode(writer);
+            }
+            writer.write(getOffset()+"</"+ELEMENT+">\n");
+        }
+        
+     
+    }
+    
+    /**
+     * Exports header defined for this type of node to the OutputStream.
+     *
+     * @param out The OutputStream.
+     */
+    public OutputStreamWriter exportHeader(OutputStream out) throws IOException{
+        //OutputStreamWriter writer = new OutputStreamWriter(out,"UTF-8")
+        
+        OutputStreamWriter writer = new OutputStreamWriter(out,"UTF-8");
+        writer.write(HEADER);
+        return writer;
+    }
+    
+    /**
+     * Returns the XML header string
+     */
+    public String getXMLHeader(){
+        return HEADER;
+    }
+    /**
+     * Returns the XML element string
+     */
+    public String getXMLElement(){
+        return ELEMENT;
+    }
+    
+    /**
+     * Returns  the deep copy of node
+     */
+    public FavoritesNode getDeepCopy(){
+        
+	return new FavoritesNode((FavoritesItem)item.clone());
+	/*
+        FavoritesNode copy = null;
+        ObjectOutputStream out = null;
+        ObjectInputStream in = null;
+        
+        try{            
+            ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+            out = new ObjectOutputStream(bOut);
+            out.writeObject(this);
+            out.flush();
+            
+            in = new ObjectInputStream(new ByteArrayInputStream(bOut.toByteArray()));            
+            copy =(FavoritesNode) in.readObject();
+            
+            out.close();
+            in.close();
+        }catch(Exception e){
+            System.err.println(e);
+        }
+        
+        return copy;
+	*/
+
+    }
+    
+    /**
+     * Returns wheter node is visible or not
+     */
+    public boolean isVisible(){
+        return item.isVisible();
+    }
+    
+    /**
+     * Sets visibility of node
+     */
+    public void setVisible(boolean vis){
+        item.setVisible(vis);
+    }
+        
+    /**
+     * Debugging code
+     */
+    private static final boolean debug = false;
+    private static void debug(String msg) {
+  	if (debug) {
+  	    System.err.println("FavoritesNode: "+msg);
+	}
+    }
+    
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/FavoritesView.java b/jhMaster/JavaHelp/src/new/javax/help/FavoritesView.java
new file mode 100644
index 0000000000000000000000000000000000000000..98dc9f3beae4092b2c5946fee2feb8b74c48839c
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/FavoritesView.java
@@ -0,0 +1,604 @@
+/*
+ * @(#)FavoritesView.java	1.6 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help;
+
+import java.awt.Component;
+import java.net.*;
+import java.io.*;
+import java.util.Hashtable;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Vector;
+import java.util.Stack;
+import java.util.Enumeration;
+import javax.help.Map.ID;
+import javax.swing.tree.TreeNode;
+import javax.swing.tree.DefaultMutableTreeNode;
+import com.sun.java.help.impl.*;
+
+
+/**
+ * Navigational View information for the Favorites
+ *
+ * @author Richard Gregor
+ * @version   1.2     08/29/01
+ */
+public class FavoritesView extends NavigatorView{
+    /**
+     * PublicID (known to this XML processor) to the DTD for version 2.0 of the Index
+     */
+    public static final String publicIDString =
+    "-//Sun Microsystems Inc.//DTD JavaHelp Favorites Version 2.0//EN";
+    
+    // turn this on if you want messages on failures
+    private static boolean warningOfFailures = false;    
+    /**
+     * The HelpSet
+     */
+    private HelpSet hs;
+    /**
+     * Determines wheter save action of favorites file is enabled or not
+     */
+    private boolean enabledSave = true;
+
+    /**
+     * Construct an FavoritesView with some given data.  Locale defaults to that
+     * of the HelpSet.
+     *
+     * @param hs The HelpSet that provides context information
+     * @param name The name of the View
+     * @param label The label (to show the user) of the View
+     * @param params A hashtable providing different key/values for this type.
+     * A null for params is valid.
+     */
+    public FavoritesView(HelpSet hs,
+			 String name,
+			 String label,
+			 Hashtable params) {
+        super(hs, name, label, hs.getLocale(), params);        
+    }
+    
+    /**
+     * Constructs an FavoritesView with some given data.
+     *
+     * @param hs The HelpSet that provides context information
+     * @param name The name of the View
+     * @param label The label (to show the user) of the View
+     * @param locale The default locale to interpret the data in this TOC. A
+     * null for locale will be interpreted as the defaultLocale.
+     * @param params A Hashtable providing different key/values for this type
+     * A null for params is valid.
+     */
+    public FavoritesView(HelpSet hs,
+			 String name,
+			 String label,
+			 Locale locale,
+			 Hashtable params) {
+        super(hs, name, label, locale, params);       
+    }
+    
+    /**
+     * create a navigator for a given model.
+     * @param model The HelpModel to create this navigator with. A null model
+     * is valid.
+     * @return The appropriate Component for this view.
+     */
+    public Component createNavigator(HelpModel model) {
+        return new JHelpFavoritesNavigator(this, model);
+    }
+    
+    /**
+     * Get the Index navigators mergeType. Overrides getMergeType in NavigatorView
+     */
+    public String getMergeType() {
+	String mergeType = super.getMergeType();
+	if (mergeType == null) {
+	    return "javax.help.NoMerge";
+	}
+	return mergeType;
+    }
+
+    /**
+     * Gets a DefaultMutableTreeNode representing the
+     * information in this view instance.
+     *
+     * The default implementation parses the data in the URL, but a subclass may
+     * override this method and provide a different implemenation. For example,
+     * it may create the tree programatically.
+     */
+    public FavoritesNode getDataAsTree() {
+        HelpSet hs = getHelpSet();
+        debug("helpSet in "+this+hs.toString());
+
+	return (FavoritesNode)parse(hs, hs.getLocale(), 
+				    new DefaultFavoritesFactory());
+    }
+    
+    /**
+     * Public method for parsing the Favorites in a URL.
+     * It returns a DefaultMutableTreeNode and its children
+     * that correspond to the favoritesItems in the Favorites.  The factory is invoked to create
+     * the TreeItems that are included in the DefaultMutableTreeNode as user
+     * data.
+     *
+     * @param url Location of the Favorites. If null, causes null value to be returned.
+     * @param hs The HelpSet context for this Favorites. Null hs is ignored.
+     * @param locale The default locale to interpret the data in this Favorites. Null
+     * locale is treated as the default locale.
+     * @param factory A factory instance that is used to create the FavoritesItems
+     * @return a TreeNode that represents the Favorites. Returns null if parsing errors
+     * were encountered.
+     */
+    public FavoritesNode parse(HelpSet hs, Locale locale, TreeItemFactory factory) {
+        Reader src;
+        DefaultMutableTreeNode node = null;
+        URL url= null;
+        try {            
+            String user_dir = System.getProperty("user.home");
+            File file = new File(user_dir+File.separator+".JavaHelp"+File.separator+"Favorites.xml");            
+            if(!file.exists())
+                return new FavoritesNode(new FavoritesItem("Favorites"));
+            try{
+                url = file.toURL();
+            }catch(MalformedURLException e){
+                System.err.println(e);
+            }
+            
+            URLConnection uc = url.openConnection();
+            src = XmlReader.createReader(uc);
+            factory.parsingStarted(url);
+            node = (new FavoritesParser(factory)).parse(src, hs, locale);
+            src.close();
+        } catch (Exception e) {
+            factory.reportMessage("Exception caught while parsing "+url+
+            e.toString(),
+            false);
+        }
+        return (FavoritesNode)factory.parsingEnded(node);
+    }
+    
+
+    /**
+     * Saves favorites file
+     *
+     * @param node The FavoritesNode
+     */
+    
+    public void saveFavorites(FavoritesNode node){
+        if(!enabledSave)
+            return;
+        try{
+            FileOutputStream out;
+            String user_dir = System.getProperty("user.home");
+            File file = new File(user_dir+File.separator+".JavaHelp");
+            file.mkdirs();                            
+            String userFile = file.getPath()+File.separator+"Favorites.xml";
+            debug("new file:"+userFile);
+            node.export(out = new FileOutputStream(userFile));
+            out.close();
+        }catch(SecurityException se){
+            enabledSave = false;
+            se.printStackTrace();
+        }catch(Exception excp){
+            excp.printStackTrace();
+        }
+    }
+    /**
+     * A default TreeItemFactory that can be used to parse Favorites items as used
+     * by this navigator.
+     */
+    public static class DefaultFavoritesFactory implements TreeItemFactory{
+        private Vector messages = new Vector();
+        private URL source;
+        private boolean validParse = true;
+        
+        /**
+         * Parsing has started
+         */
+        public void parsingStarted(URL source) {
+            if (source == null) {
+                throw new NullPointerException("source");
+            }
+            this.source = source;
+        }
+        
+        /**
+         * Process a DOCTYPE
+         */
+        public void processDOCTYPE(String root,
+				   String publicID,
+				   String systemID) {
+            if (publicID == null ||
+            !publicID.equals(publicIDString)) {
+                reportMessage(HelpUtilities.getText("favorites.invalidFavoritesFormat", publicID), false);
+            }
+        }
+        
+        /**
+         * We have found a PI; ignore it
+         */
+        public void processPI(HelpSet hs, String target, String data) {
+        }
+        
+        /**
+         * Creates an FavoritesItem with the given data.
+         * @param tagName The favorites type to create.
+         * Valid types are "favoriteitem". Null or invalid types throw an
+         * IllegalArgumentException.
+         * @param atts Attributes of the Item. Valid attributes are "target"
+         * and "text". A null <tt>atts</tt> is valid and means no attributes.
+         * @param hs The HelpSet this item was created under.
+         * @param locale Locale of this item. A null locale is valid.
+         * @returns A fully constructed TreeItem.
+         * @throws IllegalArgumentException if tagname is null or invalid.
+         */
+        public TreeItem createItem(String tagName,
+				   Hashtable atts,
+				   HelpSet hs,
+				   Locale locale) {
+            if (tagName == null || !tagName.equals("favoriteitem")) {
+                throw new IllegalArgumentException("tagName");
+            }
+            FavoritesItem item = null;
+            String target = null;
+            String name = null;
+            String mergeType = null;
+            String url = null;
+            String hstitle = null;
+            
+            if (atts != null ) {
+                target = (String) atts.get("target");
+                debug("target:"+target);
+                name = (String) atts.get("text");                
+                url = (String) atts.get("url");
+                hstitle = (String) atts.get("hstitle");            
+                item = new FavoritesItem(name,target,url,hstitle,locale);       
+                if((item.getTarget() == null) &&(item.getURLSpec() == null))
+                    item.setAsFolder();
+            }else
+                item = new FavoritesItem();
+            
+                       
+       
+        return item;
+    }
+    
+    /**
+     * Creates a default FavoritesItem.
+     */
+    public TreeItem createItem() {
+        debug("empty item created");
+        return new FavoritesItem();
+    }
+    
+    /**
+     * Reports an error message.
+     */
+    public void reportMessage(String msg, boolean validParse) {
+        messages.addElement(msg);
+        this.validParse = this.validParse && validParse;
+    }
+    
+    /**
+     * Lists all the error messages.
+     */
+    public Enumeration listMessages() {
+        return messages.elements();
+    }
+    
+    /**
+     * Parsing has ended.  The last chance to do something
+     * to the node
+     * @param node The DefaultMutableTreeNode that has been built during the
+     * the parsing. If <tt>node</tt> is null or there were parsing errors a null
+     * is returned.
+     * @returns A valid DefaultMutableTreeNode if the parsing succeded or null
+     * if it failed
+     */
+    public DefaultMutableTreeNode parsingEnded(DefaultMutableTreeNode node) {
+        DefaultMutableTreeNode back = node;
+        if (! validParse) {
+            // A parse with problems...
+            back = null;
+            System.err.println("Parsing failed for "+source);
+            for (Enumeration e = messages.elements();
+            e.hasMoreElements();) {
+                String msg = (String) e.nextElement();
+                // need to think about this one...
+                System.err.println(msg);
+            }
+        }
+        return back;
+    }    
+    
+    }
+
+
+    /**
+ * Inner class for parsing an Favorites stream.
+ *
+ * WARNING!! This class is an interim solution until JH moves to a
+ * real XML parser.  This is not a public class.  Clients should only use
+ * the parse method in the enclosing class.
+ */
+
+    private static class FavoritesParser implements ParserListener {
+	private HelpSet currentParseHS; // HelpSet we are parsing into
+	private Stack nodeStack;	// to track the parsing
+	private Stack itemStack;
+	private Stack tagStack;
+	private Locale defaultLocale;
+	private Locale lastLocale;
+	private boolean startedfavorites;
+	private TreeItemFactory factory;
+    
+	/**
+	 * Creates an Favorites Parser using a factory instance to create the item nodes.
+	 *
+	 * @param factory The ItemTreeFactory instance to use when a node
+	 * has been recognized.
+	 */
+    
+	FavoritesParser(TreeItemFactory factory) {
+	    this.factory = factory;
+	}
+    
+	/**
+	 * Parse a reader into a DefaultMutableTreeNode.
+	 * Only one of these at a time.
+	 */
+	synchronized FavoritesNode parse(Reader src,
+					 HelpSet context,
+					 Locale locale)
+	    throws IOException {
+		nodeStack = new Stack();
+		itemStack = new Stack();
+		tagStack = new Stack();
+        
+		if (locale == null) {
+		    defaultLocale = Locale.getDefault();
+		} else {
+		    defaultLocale = locale;
+		}
+		lastLocale = defaultLocale;
+        
+		FavoritesNode node = new FavoritesNode(new FavoritesItem("Favorites"));
+		nodeStack.push(node);
+        
+		currentParseHS = context;
+        
+		Parser parser = new Parser(src); // the XML parser instance
+		parser.addParserListener(this);
+		parser.parse();
+		return node;
+	}
+    
+	/**
+	 *  A Tag was parsed.  This method is not intended to be of general use.
+	 */
+	public void tagFound(ParserEvent e) {
+	    Locale locale = null;
+	    Tag tag = e.getTag();
+	    TagProperties attr = tag.atts;
+        
+	    if (attr != null) {
+		String lang = attr.getProperty("xml:lang");
+		locale = HelpUtilities.localeFromLang(lang);
+	    }
+	    if (locale == null) {
+		locale = lastLocale;
+	    }
+        
+	    if (tag.name.equals("favoriteitem")) {
+		if (!startedfavorites) {
+		    factory.reportMessage(HelpUtilities.getText("favorites.invalidFavoritesFormat"),
+					  false);
+		}
+		if (tag.isEnd && ! tag.isEmpty) {
+		    nodeStack.pop();
+		    itemStack.pop();
+		    removeTag(tag);
+		    return;
+		}
+            
+		TreeItem item = null;
+		try {
+		    Hashtable t = null;
+		    if (attr != null) {
+			t = attr.getHashtable();
+		    }
+		    item = factory.createItem("favoriteitem",
+					      t,
+					      currentParseHS,
+					      locale);
+		} catch (Exception ex) {
+		    if (warningOfFailures) {
+			String id=null;
+			if (attr != null) {
+			    id = attr.getProperty("target");
+			}
+			System.err.println("Failure in FavoritesItem Creation; ");
+			System.err.println("  id: "+id);
+			System.err.println("  hs: "+currentParseHS);
+			ex.printStackTrace();
+		    }
+		    debug("empty item !");
+		    item = factory.createItem();
+		}
+            
+		FavoritesNode node = new FavoritesNode((FavoritesItem)item);
+		FavoritesNode parent =
+		    (FavoritesNode) nodeStack.peek();
+		parent.add(node);
+		if (! tag.isEmpty) {
+		    itemStack.push(item);
+		    nodeStack.push(node);
+		    addTag(tag, locale);
+		}
+	    }  else if (tag.name.equals("favorites")) {
+		if (!tag.isEnd) {
+		    if (attr != null) {
+			String version = attr.getProperty("version");
+			if (version != null &&
+			    version.compareTo("2.0") != 0) {
+			    factory.reportMessage(HelpUtilities.getText("favorites.unknownVersion", version), false);
+			}
+		    }
+		    if (startedfavorites) {
+			factory.reportMessage(HelpUtilities.getText("favorites.invalidFavoritesFormat"),
+					      false);
+		    }
+		    startedfavorites = true;
+		    addTag(tag, locale);
+		} else {
+		    if (startedfavorites) {
+			startedfavorites = false;
+		    }
+		    removeTag(tag);
+		}
+		return;
+	    }
+	}
+    
+	/**
+	 *  A PI was parsed.  This method is not intended to be of general use.
+	 */
+	public void piFound(ParserEvent e) {
+	    // ignore
+	}
+    
+	/**
+	 *  A DOCTYPE was parsed.  This method is not intended to be of general use.
+	 */
+	public void doctypeFound(ParserEvent e) {
+	    // ignore for now
+	    factory.processDOCTYPE(e.getRoot(), e.getPublicId(), e.getSystemId());
+	}
+    
+	/**
+	 * A continous block of text was parsed.
+	 */
+	public void textFound(ParserEvent e) {
+	    if (tagStack.empty()) {
+		return;		// ignore
+	    }
+	    LangElement le = (LangElement) tagStack.peek();
+	    Tag tag = (Tag) le.getTag();
+	    if (tag.name.equals("favoriteitem")) {
+		FavoritesItem item = (FavoritesItem) itemStack.peek();
+		String oldName = item.getName();
+		if (oldName == null) {
+		    item.setName(e.getText().trim());
+		} else {
+		    item.setName(oldName.concat(e.getText()).trim());
+		}
+	    }
+	}
+    
+	// The remaing events from Parser are ignored
+	public void commentFound(ParserEvent e) {}
+    
+	public void errorFound(ParserEvent e){
+	    factory.reportMessage(e.getText(), false);
+	}
+    
+	/**
+	 * Keeps track of tags and their locale attributes.
+	 */
+	protected void addTag(Tag tag, Locale locale) {
+	    LangElement el = new LangElement(tag, locale);
+	    tagStack.push(el);
+	    // It's possible for lastLocale not be specified ergo null.
+	    // If it is then set lastLocale to null even if locale is null.
+	    // It is impossible for locale to be null
+	    if (lastLocale == null) {
+		lastLocale = locale;
+		return;
+	    }
+	    if (locale == null) {
+		lastLocale = locale;
+		return;
+	    }
+	    if (! lastLocale.equals(locale)) {
+		lastLocale = locale;
+	    }
+	}
+    
+	/**
+	 * Removes a tag from the tagStack. The tagStack is
+	 * used to keep track of tags and locales.
+	 */
+	protected void removeTag(Tag tag) {
+	    LangElement el;
+	    String name = tag.name;
+	    Locale newLocale=null;
+        
+	    for (;;) {
+		if (tagStack.empty())
+		    break;
+		el = (LangElement) tagStack.pop();
+		if (! el.getTag().name.equals(name)) {
+		    if (tagStack.empty()) {
+			newLocale = defaultLocale;
+		    } else {
+			el = (LangElement) tagStack.peek();
+			newLocale = el.getLocale();
+		    }
+		    break;
+		}
+	    }
+	    // It's possible for lastLocale not be specified ergo null.
+	    // If it is then set lastLocale to null even if locale is null.
+	    // It also possible for locale to be null so if lastLocale is set
+	    // then reset lastLocale to null;
+	    // Otherwise if lastLocale doesn't equal locale reset lastLocale to locale
+	    if (lastLocale == null) {
+		lastLocale = newLocale;
+		return;
+	    }
+	    if (newLocale == null) {
+		lastLocale = newLocale;
+		return;
+	    }
+	    if (! lastLocale.equals(newLocale)) {
+		lastLocale = newLocale;
+	    }
+	}
+    
+    }
+
+    /**
+     * Debugging code
+     */
+    private static final boolean debug = false;
+    private static void debug(String msg) {
+	if (debug) {
+	    System.err.println("FavoritesView: "+msg);
+	}
+    }
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/FlatMap.java b/jhMaster/JavaHelp/src/new/javax/help/FlatMap.java
new file mode 100644
index 0000000000000000000000000000000000000000..b3fb909de77a46c76a841b09bd85c7fb1f96294b
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/FlatMap.java
@@ -0,0 +1,480 @@
+/*
+ * @(#)FlatMap.java	1.36 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help;
+
+import java.net.URL;
+import java.net.URLConnection;
+import java.net.MalformedURLException;
+import java.util.*;
+import java.io.*;
+import java.beans.*;
+import javax.help.event.*;
+import javax.help.Map.ID;
+import com.sun.java.help.impl.*;
+
+/**
+ * A FlatMap is a simple implementation of a Map.  It is used to represent a
+ * Map for a single file.
+ *
+ * @author Eduardo Pelegri-Llopart
+ * @version	1.18	01/22/99
+ */
+public class FlatMap implements Map, Serializable {
+    private URL base;		// URL to this map
+    private ResourceBundle resource; // the resource
+    private HelpSet helpset;	// the top HelpSet
+
+    /**
+     * PublicID (known to this XML processor) to the DTD for version 1.0 of the Map
+     */
+    public static final String publicIDString =
+        "-//Sun Microsystems Inc.//DTD JavaHelp Map Version 1.0//EN";
+
+    /**
+     * PublicID (known to this XML processor) to the DTD for version 1.0 of the Map
+     */
+    public static final String publicIDString_V2 =
+        "-//Sun Microsystems Inc.//DTD JavaHelp Map Version 2.0//EN";
+
+  /**
+     * Create a FlatMap from a given URL.
+     *
+    * @param source The URL that is the source for all references in this Map.
+    * @param hs The HelpSet providing "context" for this Map.
+    * @throws IllegalArgumentException if hs doesn't have nested HelpSets.
+     */
+    public FlatMap(URL base, HelpSet hs) throws IOException {
+	debug("Creating FlatMap for: "+base);
+
+	// Verify that this helpset indeed does not have nested HelpSets.
+	for (Enumeration e = hs.getHelpSets();
+	     e.hasMoreElements(); ) {
+	    throw new IllegalArgumentException
+		("Cannot create - HelpSet is not flat");
+	}
+
+	//	InputStream is = base.openStream();
+	//	resource = new MapResourceBundle(is);
+	resource = new FlatMapResourceBundle(base);
+        this.base = base;
+	this.helpset = hs;
+    }
+
+    /**
+     * The HelpSet for this Map.
+     */
+    public HelpSet getHelpSet() {
+	return helpset;
+    }
+
+    /**
+     * Determines whether the given ID is valid. If hs is null
+     * it is ignored.
+     * 
+     * @param id The String ID.
+     * @param hs The HelpSet against which to resolve the string.
+     * @return True if id is valid, false if not valid.
+     */
+
+    public boolean isValidID(String id, HelpSet hs) {
+	debug("isValidID "+id);
+
+	try {
+	    String tmp = resource.getString(id);
+	} catch (MissingResourceException e) {
+	    return false;
+	}
+	return true;
+    }
+
+    /**
+     * Gets an enumeration of all the IDs in a Map.
+     *
+     * @return An enumeration of all the IDs in a Map.
+     */
+    public Enumeration getAllIDs() {
+	return new FlatEnumeration(resource.getKeys(), helpset);
+    }
+
+    /**
+     * Gets the URL that corresponds to a given ID in the map.
+     *
+     * @param iden The iden to get the URL for. If iden is null it is
+     * treated as an unresolved ID and will return null.
+     * @return URL The matching URL.  Null if this map cannot solve the ID
+     * @exception MalformedURLException if the URLspecification found  is malformed
+     */
+    public URL getURLFromID(ID iden) throws MalformedURLException {
+	debug("getURLFromID("+iden+")");
+
+	String id = iden.id;
+	HelpSet hs = iden.hs;
+	if (id == null) {
+	    return null;
+	}
+	String tmp = null;
+	try {
+	    tmp = resource.getString(id);
+	    URL back = new URL(base, tmp);
+	    return back;
+	} catch (MissingResourceException e) {
+	    return null;
+	}
+    }
+
+    /**
+     * Determines if the URL corresponds to an ID in the Map.
+     *
+     * @param url The URL to check on.
+     * @return true If this is an ID, otherwise false.
+     */
+    public boolean isID(URL url) {
+	URL tmp;
+	for (Enumeration e = resource.getKeys() ; e.hasMoreElements() ;) {
+	    try {
+		String key = (String) e.nextElement();
+		tmp = new URL(base, (String) resource.getObject(key));
+		// sameFile() ignores the anchor! - epll
+		if (url.sameFile(tmp) == true) {
+		    return true;
+		}
+	    } catch (Exception ex) {
+	    }
+	}
+	return false;
+    }
+
+
+    /**
+     * Gets the ID for this URL.
+     * 
+     * @param url The URL to get the ID for.
+     * @return The id (Map.ID) or null if URL is not an ID.
+     */
+    public ID getIDFromURL(URL url) {
+	String tmp;
+	URL tmpURL;
+	if (url == null) return null;
+	String urlString = url.toExternalForm();
+	for (Enumeration e = resource.getKeys() ; e.hasMoreElements() ;) {
+	    String key = (String) e.nextElement();
+	    try {
+		tmp = resource.getString(key);
+		tmpURL = new URL(base, tmp);
+
+		// Sometimes tmp will be null because not all keys are ids
+		if (tmpURL == null) continue;
+		String tmpString = tmpURL.toExternalForm();
+		if (urlString.compareTo(tmpString) == 0) {
+		    return ID.create(key, helpset);
+		}
+	    } catch (Exception ex) {
+	    }
+	}
+	return null;
+    }
+
+    /**
+     * Determines the ID that is "closest" to this URL (with a given anchor).
+     *
+     * The definition of this is up to the implementation of Map.  In particular,
+     * it may be the same as getIDFromURL().
+     *
+     * @param url A URL
+     * @return The closest ID in this map to the given URL
+     */
+    public ID getClosestID(URL url) {
+	return getIDFromURL(url);
+    }
+
+
+    /**
+     * Determines the IDs related to this URL.
+     *
+     * @param URL The URL to compare the Map IDs to.
+     * @return Enumeration of Map.IDs
+     */
+    public Enumeration getIDs(URL url) {
+	String tmp=null;
+	URL tmpURL=null;
+	Vector ids = new Vector();
+	for (Enumeration e = resource.getKeys() ; e.hasMoreElements() ;) {
+	    String key = (String) e.nextElement();
+	    try {
+		tmp = resource.getString(key);
+		tmpURL = new URL(base, tmp);
+		if (url.sameFile(tmpURL) == true) {
+		    ids.addElement(key);
+		}
+	    } catch (Exception ex) {
+	    }
+	}
+	return new FlatEnumeration(ids.elements(), helpset);
+    }
+
+    private static class FlatEnumeration implements Enumeration {
+	private Enumeration e;
+	private HelpSet hs;
+
+	public FlatEnumeration(Enumeration e, HelpSet hs) {
+	    this.e = e;
+	    this.hs = hs;
+	}
+
+	public boolean hasMoreElements() {
+	    return e.hasMoreElements();
+	}
+
+	public Object nextElement() {
+	    Object back = null;
+	    try {
+		back = ID.create((String) e.nextElement(), hs);
+	    } catch (Exception ex) {
+	    }
+	    return back;
+	}
+    }
+
+
+    /**
+     * FlatMapResourceBundle is a ResourceBundle but unlike most 
+     * ResourceBundles it is not locale-based and is loaded via the
+     * constructor, not getBundle.
+     */
+    protected class FlatMapResourceBundle extends ResourceBundle 
+        implements ParserListener, Serializable  
+    {
+
+	private Hashtable lookup = null;
+	private boolean startedmap;
+	private URL source;
+
+	/**
+	 * Creates the FlatMap from the data.
+	 */
+	public FlatMapResourceBundle(URL url) {
+	    source = url;
+	    Reader src;
+	    try {
+		URLConnection uc = url.openConnection();
+		src = XmlReader.createReader(uc);
+		parse(src);
+		src.close();
+	    } catch (Exception e) {
+		reportMessage("Exception caught while parsing "+url+" "+
+				   e.toString(), false);
+	    }
+	    parsingEnded();
+	    for (Enumeration e = lookup.keys() ; e.hasMoreElements() ;) {
+		String key1 = (String) e.nextElement();
+		String url1 = (String) lookup.get(key1);
+	    }
+	}
+
+	/**
+	 * Overrides ResourceBundle, same semantics.
+	 */
+	public final Object handleGetObject(String key) {
+	    return lookup.get(key); // this class ignores locales
+	}
+
+	/**
+	 * Implements ResourceBundle.getKeys.
+	 */
+	public Enumeration getKeys() {
+	    return lookup.keys();
+	}
+
+	/**
+	 * Parses a reader into a MutableTreeNode
+	 * Only one of these at a time.
+	 */
+	synchronized void parse(Reader src)
+	    throws IOException 
+	{
+	    lookup = new Hashtable(10);
+
+	    Parser parser = new Parser(src); // the XML parser instance
+	    parser.addParserListener(this);
+	    parser.parse();
+	}
+
+	/**
+	 *  A tag was parsed.
+	 */
+	public void tagFound(ParserEvent e) {
+	    Locale locale = null;
+	    Tag tag = e.getTag();
+	    FlatMap.debug("TagFound: "+tag.name);
+	    TagProperties attr = tag.atts;
+
+	    // Nothing tricky about mapID it doesn't have any hierarchy to it.
+	    if (tag.name.equals("mapID")) {
+		if (!startedmap) {
+		    parsingError("map.invalidMapFormat");
+		}
+
+		String target = null;
+		String url = null;
+		if (attr != null) {
+		    target = attr.getProperty("target");
+		    url = attr.getProperty("url");
+		}
+		if (target == null || url == null) {
+		    reportMessage("Failure in mapID Creation;", true);
+		    reportMessage("  target: "+ target, true);
+		    reportMessage("  url: "+ url, true);
+		    return;
+		}
+		lookup.put(target, url);
+		return;
+	    } else if (tag.name.equals("map")) {
+		if (!tag.isEnd) {
+		    if (attr != null) {
+		        String version = attr.getProperty("version");
+			if (version != null && 
+			    (version.compareTo("1.0") != 0 &&
+			     version.compareTo("2.0") != 0)) {
+			    parsingError("map.unknownVersion", version);
+			}
+		    }
+		    if (startedmap) {
+			parsingError("map.invalidMapFormat");
+		    }
+		    startedmap = true;
+		} else {
+		    if (startedmap) {
+			startedmap = false;
+		    }
+		}
+		return;
+	    }
+	}
+
+	/**
+	 *  A PI was parsed.  This method is not intended to be of general use.
+	 */
+	public void piFound(ParserEvent e) {
+	    // ignore
+	}
+
+	/**
+	 *  A DOCTYPE was parsed.  This method is not intended to be of general use.
+	 */
+	public void doctypeFound(ParserEvent e) {
+	    String publicID = e.getPublicId();
+	    if (publicID == null ||
+		(publicID.compareTo(publicIDString) != 0 &&
+		 publicID.compareTo(publicIDString_V2) != 0)) {
+		parsingError("map.wrongPublicID", publicID);
+	    }
+	}
+
+	/**
+	 * A continous block of text was parsed.
+	 */
+	public void textFound(ParserEvent e) {
+	    // At the current time I don't care about text. All the text is
+	    // within the attributes in the tag
+	}
+
+	// The remaing events from Parser are ignored
+	public void commentFound(ParserEvent e) {}
+
+	public void errorFound(ParserEvent e){
+	    reportMessage(e.getText(), false);
+	}
+
+
+	private Vector messages = new Vector();
+	private boolean validParse = true;
+
+	/**
+	 * Reports an error message.
+	 */
+	public void reportMessage(String msg, boolean validParse) {
+	    messages.addElement(msg);
+	    this.validParse = this.validParse && validParse;
+	}
+
+	/**
+	 * Enumerates all the error messages.
+	 */
+	public Enumeration listMessages() {
+	    return messages.elements();
+	}
+
+	/**
+	 * Parsing has ended.  We are given a last chance to do something
+	 * to the HelpSet
+	 */
+	private void parsingEnded() {
+	    if (! validParse) {
+		if (lookup != null) {
+		    lookup.clear();
+		}
+
+		// A parse with problems...
+		FlatMap.debug("Parsing failed for "+source);
+
+		for (Enumeration e = messages.elements();
+		     e.hasMoreElements();) {
+		    String msg = (String) e.nextElement();
+
+		    FlatMap.debug(msg);
+		}
+	    } else {
+		// little memory clean up
+		source = null;
+	    }
+	}
+
+	// Convenience methods
+	private void parsingError(String key) {
+	    String s = HelpUtilities.getText(key);
+	    reportMessage(s, false); // tree will be wrong
+	}
+
+	private void parsingError(String key, String s) {
+	    String msg = HelpUtilities.getText(key, s);
+	    reportMessage(msg, false); // tree will be wrong
+	}
+
+    }
+
+    /**
+     * For printf debugging...
+     */
+    private static final boolean debug = false;
+    private static void debug(String str) {
+        if (debug) {
+            System.out.println("FlatMap: " + str);
+        }
+    }
+
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/ForwardAction.java b/jhMaster/JavaHelp/src/new/javax/help/ForwardAction.java
new file mode 100644
index 0000000000000000000000000000000000000000..0e9da663df41e3175d244aa56a51f064ed5f1a15
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/ForwardAction.java
@@ -0,0 +1,188 @@
+/*
+ * @(#)ForwardAction.java	1.4 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.help.*;
+import javax.help.event.*;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.Stack;
+import javax.swing.*;
+
+/**
+ *
+ * @author Stepan Marek
+ * @version	1.4	10/30/06
+ */
+public class ForwardAction extends AbstractHelpAction implements MouseListener, HelpHistoryModelListener {
+
+    private static final String NAME = "ForwardAction";
+    
+    private static final int DELAY = 500;    
+    private Timer timer;
+    private HelpHistoryModel historyModel;
+    
+    /** Creates new ForwardAction */
+    public ForwardAction(Object control) {
+        super(control, NAME);
+        if (control instanceof JHelp) {
+            JHelp help = (JHelp)control;            
+            historyModel = help.getHistoryModel();
+            historyModel.addHelpHistoryModelListener(this);
+            
+            setEnabled(historyModel.getIndex() > 0);
+            
+            putValue("icon", UIManager.getIcon(NAME + ".icon"));
+            
+	    Locale locale = null;
+	    try {
+		locale = help.getModel().getHelpSet().getLocale();
+	    } catch (NullPointerException npe) {
+		locale = Locale.getDefault();
+	    }
+            putValue("tooltip", HelpUtilities.getString(locale, "tooltip." + NAME));
+            putValue("access", HelpUtilities.getString(locale, "access." + NAME));            
+        }
+    }
+
+    /**
+     * Invoked when the mouse exits a component.
+     */
+    public void mouseExited(MouseEvent e) {
+    }    
+    
+    /**
+     * Invoked when a mouse button has been released on a component.
+     */
+    public void mouseReleased(MouseEvent e) {
+        if (timer != null) {
+            timer.stop();
+        }
+    }
+    
+    /**
+     * Invoked when a mouse button has been pressed on a component.
+     */
+    public void mousePressed(MouseEvent e) {
+        timer = new Timer(DELAY, new TimeListener(e));
+        timer.start();
+    }
+    
+    /**
+     * Invoked when the mouse has been clicked on a component.
+     */
+    public void mouseClicked(MouseEvent e) {
+        if ((historyModel != null) && isEnabled()) {
+            historyModel.goForward();
+        }
+    }
+    
+    /**
+     * Invoked when the mouse enters a component.
+     */
+    public void mouseEntered(MouseEvent e) {
+    }
+
+    private class TimeListener implements ActionListener {
+        
+        private MouseEvent e;
+        
+        public TimeListener(MouseEvent e) {
+            this.e = e;
+        }
+        
+        public void actionPerformed(ActionEvent evt){
+            timer.stop();
+            if (ForwardAction.this.isEnabled()) {
+                ForwardAction.this.showForwardHistory(e);
+            }
+        }
+    }
+
+    private class HistoryActionListener implements ActionListener {
+        
+        private int index;
+        
+        public HistoryActionListener(int index) {
+            this.index = index;          
+        }
+        
+        public void actionPerformed(java.awt.event.ActionEvent event) {
+            if(historyModel != null) {
+                historyModel.setHistoryEntry(index);
+            }
+        }        
+    }
+
+    /**
+     * Shows popup with forward history entries
+     */
+    private void showForwardHistory(MouseEvent e) {
+        
+        JPopupMenu forwardMenu = new JPopupMenu("Forward History");
+        
+        if (historyModel == null) {
+            return;
+        }
+        
+        Locale locale = ((JHelp)getControl()).getModel().getHelpSet().getLocale();
+        Enumeration items = historyModel.getForwardHistory().elements();
+        JMenuItem mi = null;
+        int index = historyModel.getIndex() + 1;
+        //while(items.hasMoreElements()){
+        for(int i = 0; items.hasMoreElements(); i++) {
+            HelpModelEvent item = (HelpModelEvent) items.nextElement();
+            if(item != null) {
+                String title = item.getHistoryName();
+                if (title == null) {                    
+                    title = HelpUtilities.getString(locale, "history.unknownTitle");
+                }
+                mi = new JMenuItem(title);
+                //mi.setToolTipText(item.getURL().getPath());
+                mi.addActionListener(new HistoryActionListener(i + index));
+                forwardMenu.add(mi);
+            }
+        }        
+       // if(e.isPopupTrigger())
+        forwardMenu.show(e.getComponent(),e.getX(),e.getY());
+        
+    }
+
+    /**
+     * Tells the listener that the history has changed.
+     * Will enable/disable the Action depending on the events previous flag
+     *
+     * @param e The HelpHistoryModelEvent
+     */
+    public void historyChanged(HelpHistoryModelEvent e) {
+        setEnabled(e.isNext());
+    }
+    
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/GlossaryView.java b/jhMaster/JavaHelp/src/new/javax/help/GlossaryView.java
new file mode 100644
index 0000000000000000000000000000000000000000..ae3abafdb695ddaf04e68ae56dbcb845bc892814
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/GlossaryView.java
@@ -0,0 +1,88 @@
+/*
+ * @(#)GlossaryView.java	1.2 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help;
+
+import java.awt.Component;
+import java.util.Hashtable;
+import java.util.Locale;
+import javax.help.HelpSet;
+import javax.help.HelpModel;
+import javax.help.IndexView;
+
+/**
+ * View information for a Glossary Navigator
+ *
+ * @author	Roger Brinkley
+ * @version   1.2     10/30/06
+ */
+
+public class GlossaryView extends IndexView {
+    /**
+     * Construct a GlossaryView with some given data.  Locale defaults
+     * to that of the HelpSet
+     *
+     * @param hs The HelpSet that provides context information
+     * @param name The name of the View
+     * @param label The label (to show the user) of the View
+     * @param params A Hashtable providing different key/values for this type
+     */
+    public GlossaryView(HelpSet hs,
+			String name,
+			String label,
+			Hashtable params) {
+	super(hs, name, label, hs.getLocale(), params);
+    }
+
+    /**
+     * Construct a GlossaryViewer VIew with some given data.
+     *
+     * @param hs The HelpSet that provides context information
+     * @param name The name of the View
+     * @param label The label (to show the user) of the View
+     * @param locale The default locale to interpret data in this View
+     * @param params A Hashtable providing different key/values for this type
+     */
+    public GlossaryView(HelpSet hs,
+			String name,
+			String label,
+			Locale locale,
+			Hashtable params) {
+	super(hs, name, label, locale, params);
+    }
+
+    /**
+     * create a navigator for a given model
+     */
+    public Component createNavigator(HelpModel model) {
+	return new JHelpGlossaryNavigator(this, model);
+    }
+}
+
+
+
+
diff --git a/jhMaster/JavaHelp/src/new/javax/help/HelpAction.java b/jhMaster/JavaHelp/src/new/javax/help/HelpAction.java
new file mode 100644
index 0000000000000000000000000000000000000000..719e8d80818a56346c30e8e604e459ca93c85498
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/HelpAction.java
@@ -0,0 +1,89 @@
+/*
+ * @(#)HelpAction.java	1.2 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help;
+
+import java.beans.PropertyChangeListener;
+/**
+ * @author Stepan Marek
+ * @version	1.2	10/30/06
+ */
+public interface HelpAction {
+
+    /** Getter for property enabled.
+     * @return Value of property enabled.
+     */
+    public boolean isEnabled();
+    
+    /** Setter for property enabled.
+     * @param enabled New value of property enabled.
+     */
+    public void setEnabled(boolean enabled);
+
+    /** Getter for property control.
+     * @return Value of property control.
+     */
+    public Object getControl();
+
+    /**
+     * Gets one of this object's properties
+     * using the associated key.
+     * @see #putValue
+     */
+    public Object getValue(String key);
+
+    /**
+     * Sets one of this object's properties
+     * using the associated key. If the value has
+     * changed, a <code>PropertyChangeEvent</code> is sent
+     * to listeners.
+     *
+     * @param key    a <code>String</code> containing the key
+     * @param value  an <code>Object</code> value
+     */
+    public void putValue(String key, Object value);
+    
+    /**
+     * Adds a <code>PropertyChange</code> listener. Containers and attached
+     * components use these methods to register interest in this 
+     * <code>Action</code> object. When its enabled state or other property
+     * changes, the registered listeners are informed of the change.
+     *
+     * @param listener  a <code>PropertyChangeListener</code> object
+     */
+    public void addPropertyChangeListener(PropertyChangeListener listener);
+    
+    /**
+     * Removes a <code>PropertyChange</code> listener.
+     *
+     * @param listener  a <code>PropertyChangeListener</code> object
+     * @see #addPropertyChangeListener
+     */
+    public void removePropertyChangeListener(PropertyChangeListener listener);
+    
+}
+
diff --git a/jhMaster/JavaHelp/src/new/javax/help/HelpBroker.java b/jhMaster/JavaHelp/src/new/javax/help/HelpBroker.java
new file mode 100644
index 0000000000000000000000000000000000000000..dbae3aa0f1f68a91c9cb7c6f9784c0fecb8bc7d2
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/HelpBroker.java
@@ -0,0 +1,386 @@
+/*
+ * @(#)HelpBroker.java	1.31 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help;
+
+import java.util.Enumeration;
+import java.net.URL;
+import java.awt.Component;
+import java.awt.MenuItem;
+import java.awt.event.ActionListener;
+import java.awt.Point;
+import java.awt.Font;
+import java.awt.Dimension;
+import javax.help.Map.ID;
+import java.util.Locale;
+
+/**
+ * The HelpBroker is the default presentation of a HelpSet.
+ *
+ * A HelpBroker is an abstraction of the presentation for a HelpSet;
+ * a straight-forward implementation is a JHelp() on the HelpSet.
+ *
+ * A HelpBroker can be asked to show a given Navigational View,
+ * and can display a given ID (help topic).
+ *
+ * @author Eduardo Pelegri-Llopart
+ * @author Roger D.Brinkley
+ * @version	1.31	10/30/06
+ *
+ * @see javax.help.HelpSet
+ * @see javax.help.JHelpNavigator
+ * @see javax.help.HelpVisitListener
+ */
+
+public interface HelpBroker {
+    /**
+     * Sets the current HelpSet for this HelpBroker.
+     *
+     * @param hs The HelpSet this JavaHelp is presenting.
+     */
+    public void setHelpSet(HelpSet hs);
+
+    /**
+     * Gets the current HelpSet for this JavaHelp object.
+     *
+     * @return The HelpSet this JavaHelp is presenting.
+     */
+    public HelpSet getHelpSet();
+
+    /**
+     * Sets the presentation attributes from a HelpSet.Presentation. 
+     * The HelpSet.Presentation must be in the current HelpSet.
+     * 
+     * @param hsPres The HelpSet.Presentation
+     * @since 2.0
+     */
+     public void setHelpSetPresentation(HelpSet.Presentation hsPres);
+
+    /**
+     * Returns the locale of this object.
+     *
+     * @return The locale of this object.
+     */
+    public Locale getLocale();
+
+    /**
+     * Sets the locale of this HelpBroker.
+     * @param l The locale to become this component's locale.
+     * @see #getLocale
+     */
+    public void setLocale(Locale l);
+
+    /**
+     * Gets the font for this HelpBroker.
+     */
+    public Font getFont();
+
+    /**
+     * Sets the font for this HelpBroker.
+     *
+     */
+    public void setFont(Font f);
+
+    /**
+     * Activates the Navigator view with a given name.
+     *
+     * @exception IllegalArgumentException if the name is not valid.
+     */
+    public void setCurrentView(String name);
+
+    /**
+     * Gets name of the current navigational view.
+     *
+     * @return The name of the current navigational view.
+     */
+    public String getCurrentView();
+
+    /**
+     * Initializes the presentation.
+     * This method allows the presentation to be initialized but not displayed.
+     * Typically this is done in a separate thread to reduce the
+     * intialization time.
+     */
+    public void initPresentation();
+
+    /**
+     * Displays the presentation to the user.
+     *
+     * @param displayed Makes the presentation visible or not.
+     * @exception HelpBroker.UnsupportedOperationException If the operation is not supported.
+     */
+    public void setDisplayed(boolean displayed) throws UnsupportedOperationException;
+
+    /**
+     * Determines if the presentation is visible.
+     *
+     * @return Whether the presentation is currently visible.
+     */
+    public boolean isDisplayed();
+
+    /**
+     * Sets the position of the presentation.
+     * This operation may throw an UnsupportedOperationException if the
+     * underlying implementation does not allow this.
+     */
+    public void setLocation(Point p) throws UnsupportedOperationException;
+
+    /**
+     * Gets the location of the presentation.
+     * This operation may throw an UnsupportedOperationException if the
+     * underlying implementation does not allow this.
+     */
+    public Point getLocation() throws UnsupportedOperationException;
+
+    /**
+     * Sets the size of the presentation.
+     * This operation may throw an UnsupportedOperationException if the
+     * underlying implementation does not allow this.
+     */
+    public void setSize(Dimension d) throws UnsupportedOperationException;
+
+    /**
+     * Gets the size of the presentation.
+     * This operation may throw an UnsupportedOperationException if the
+     * underlying implementation does not allow this.
+     */
+    public Dimension getSize() throws UnsupportedOperationException;
+
+    /**
+     * Set the screen the presentation is to be displayed on
+     * This operation may throw an UnsupportedOperationException if the
+     * underlying implementation does not allow this.
+     */
+    public void setScreen(int screen) throws UnsupportedOperationException;
+
+    /**
+     * Get ths the screen the presentation is displayed on
+     * This operation may throw an UnsupportedOperationException if the
+     * underlying implementation does not allow this.
+     */
+    public int getScreen() throws UnsupportedOperationException;
+
+    /**
+     * Hides/Shows Navigational Views.
+     *
+     * @param displayed Make the navigational views visible or not.
+     */
+    public void setViewDisplayed(boolean displayed);
+
+    /**
+     * Determines if the Navigational View is visible.
+     * 
+     * @return Whether the navigational views are visible.
+     */
+    public boolean isViewDisplayed();
+
+
+    /**
+     * Displays this ID in a given presentation
+     *
+     * @param id An ID that identifies the topic to display.
+     * @param presentation The Presentation class to display the Help in.
+     * @param presentationName The name of a Presentation section from a 
+     *		HelpSet to use. For some Presentations this will also be
+     *		the name to apply to the Presentation.
+     * @exception InvalidHelpSetContextException If id.hs is not contanied in the current
+     * HelpSet of this broker.
+     * @see Presentation
+     */
+    public void showID(ID id, String presentation, String presentationName)
+	throws InvalidHelpSetContextException;
+
+    /**
+     * Displays this ID in a particular presentation
+     * 
+     * @param id A String identifying the topic to show relative to getHelpSet()
+     * @param presentation The Presentation class to display the Help in.
+     * @param presentationName The name of a Presentation section from a 
+     *		HelpSet to use. For some Presentations this will also be
+     *		the name to apply to the Presentation.
+     * @exception BadIDException if the ID is not valid in the map.
+     * @see Presentation
+     */
+    public void showID(String id, String presentation, String presentationName)
+	throws BadIDException;
+
+    /**
+     * Displays this ID.
+     *
+     * @param id An ID that identifies the topic to display.
+     * @exception InvalidHelpSetContextException If id.hs is not contanied in the current
+     * HelpSet of this broker.
+     * @see HelpModel#setCurrentID
+     */
+    public void setCurrentID(ID id) throws InvalidHelpSetContextException;
+
+    /**
+     * Displays this ID.
+     * HelpVisitListeners are notified.
+     * 
+     * @param id A String identifying the topic to show relative to getHelpSet()
+     * @exception BadIDException if the ID is not valid in the map.
+     */
+    public void setCurrentID(String id) throws BadIDException;
+
+    /**
+     * Determines The currently displayed ID (if any).
+     *
+     * @return The ID being shown.
+     */
+    public ID getCurrentID();
+
+    /**
+     * Displays this ID.
+     * HelpVisitListeners are notified.
+     * The currentID changes if there is a matching ID for this URL.
+     *
+     * @param url The URL to show
+     */
+    public void setCurrentURL(URL url);
+
+    /**
+     * Determines the currently displayed ID.
+     *
+     * @return The URL being shown.
+     */
+    public URL getCurrentURL();
+
+    /**
+     * Enables the Help key on a component. This method works best when
+     * the component is the
+     * rootPane of a JFrame in Swing implementations, or a java.awt.Window
+     * (or subclass thereof) in AWT implementations.
+     * This method sets the default
+     * helpID and HelpSet for the component and registers keyboard actions
+     * to trap the "Help" keypress. When the "Help" key is pressed, if the
+     * object with the current focus has a helpID, the helpID is displayed,
+     * otherwise the default helpID is displayed.
+     *
+     * @param comp The component to enable the keyboard actions on.
+     * @param id The default HelpID to be displayed.
+     * @param hs The default HelpSet to be displayed.
+     */
+    public void enableHelpKey(Component comp, String id, HelpSet hs);
+    /**
+     * Enables the Help key on a component. This method works best when
+     * the component is the
+     * rootPane of a JFrame in Swing implementations, or a java.awt.Window
+     * (or subclass thereof) in AWT implementations.
+     * This method sets the default
+     * helpID and HelpSet for the component and registers keyboard actions
+     * to trap the "Help" keypress. When the "Help" key is pressed, if the
+     * object with the current focus has a helpID, the helpID is displayed,
+     * otherwise the default helpID is displayed.
+     *
+     * @param comp The component to enable the keyboard actions on.
+     * @param id The default HelpID to be displayed.
+     * @param hs The default HelpSet to be displayed.
+     * @param presentation The Presentation class to display the Help in.
+     * @param presentationName The name of a Presentation section from a 
+     *		HelpSet to use. For some Presentations this will also be
+     *		the name to apply to the Presentation.
+     * @see Presentation
+     */
+    public void enableHelpKey(Component comp, String id, HelpSet hs, 
+			      String presentation, String presentationName);
+
+    /**
+     * Enables help for a component. This method sets a 
+     * component's helpID and HelpSet. 
+     *
+     * @see CSH.setHelpID
+     * @see CSH.setHelpSet
+     */
+    public void enableHelp(Component comp, String id, HelpSet hs);
+
+    /**
+     * Enables help for a MenuItem. This method sets a 
+     * component's helpID and HelpSet. 
+     *
+     * @see CSH.setHelpID
+     * @see CSH.setHelpSet
+     */
+    public void enableHelp(MenuItem comp, String id, HelpSet hs);
+
+    /**
+     * Enables help for a component. This method sets a 
+     * component's helpID and HelpSet and adds an ActionListener. 
+     * When an action is performed
+     * it displays the component's helpID and HelpSet in the default viewer.
+     * If the component is not a javax.swing.AbstractButton or a 
+     * java.awt.Button an IllegalArgumentException is thrown.
+     *
+     * @see CSH.setHelpID
+     * @see CSH.setHelpSet
+     * @see javax.swing.AbstractButton
+     * @see java.awt.Button
+     */
+    public void enableHelpOnButton(Component comp, String id, HelpSet hs)
+	throws IllegalArgumentException;
+
+    /**
+     * Enables help for a MenuItem. This method sets a 
+     * component's helpID and HelpSet and adds an ActionListener. 
+     * When an action is performed
+     * it displays the component's helpID and HelpSet in the default viewer.
+     *
+     * @see CSH.setHelpID
+     * @see CSH.setHelpSet
+     * @see java.awt.MenuItem
+     */
+    public void enableHelpOnButton(MenuItem comp, String id, HelpSet hs);
+
+    /**
+     * Enables help for an object. This method sets a 
+     * object's helpID and HelpSet and adds an ActionListener. 
+     * When an action is performed
+     * it displays the component's helpID and HelpSet in the default viewer
+     * or the presenation if defined.
+     * If the component is not a javax.swing.AbstractButton or a 
+     * java.awt.Button an IllegalArgumentException is thrown.
+     *
+     * @param comp The component to enable the keyboard actions on.
+     * @param id The default HelpID to be displayed.
+     * @param hs The default HelpSet to be displayed.
+     * @param presentation The Presentation class to display the Help in.
+     * @param presentationName The name of a Presentation section from a 
+     *		HelpSet to use. For some Presentations this will also be
+     *		the name to apply to the Presentation.
+     *
+     * @see Presentation
+     * @see CSH.setHelpID
+     * @see CSH.setHelpSet
+     * @see javax.swing.AbstractButton
+     * @see java.awt.Button
+     */
+    public void enableHelpOnButton(Object obj, String id, HelpSet hs,
+				   String presentation, 
+				   String presentationName)
+	throws IllegalArgumentException;
+
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/HelpHistoryModel.java b/jhMaster/JavaHelp/src/new/javax/help/HelpHistoryModel.java
new file mode 100644
index 0000000000000000000000000000000000000000..189f83c683493feff52c9ed499333e6b3832669d
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/HelpHistoryModel.java
@@ -0,0 +1,125 @@
+/*
+ * @(#)HelpHistoryModel.java	1.3 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help;
+
+/**
+ * History Model for HelpModel
+ *
+ * @author  Richard Gregor
+ * @version   1.3     10/30/06
+ */
+
+import java.awt.event.ActionListener;
+import javax.help.event.*;
+import java.io.Serializable;
+import java.beans.*;
+import java.util.Vector;
+import javax.help.Map.ID;
+import java.util.Enumeration;
+
+/**
+ * The interface to the history model.
+ */
+public interface HelpHistoryModel extends HelpModelListener, Serializable{
+    /**
+     * Adds a listener for the HelpHistoryModelEvent posted after the model has
+     * changed.
+     * 
+     * @param l The listener to add.
+     * @see javax.help.HelpHistoryModel#removeHelpHistoryModelListener
+     */
+    public void addHelpHistoryModelListener(HelpHistoryModelListener l);
+
+    /**
+     * Removes a listener previously added with <tt>addHelpHistoryModelListener</tt>
+     *
+     * @param l The listener to remove.
+     * @see javax.help.HelpHistoryModel#addHelpHistoryModelListener
+     */
+    public void removeHelpHistoryModelListener(HelpHistoryModelListener l);
+       
+    /**
+     * Discards a history
+     */
+    public void discard();
+    /**
+     * Sets a next history entry
+     */
+    public void goForward();
+    
+    /**
+     * Sets a previous history entry
+     */
+    public void goBack();
+    
+    /**
+     * Returns a backward history list
+     */
+    public Vector getBackwardHistory();
+    
+    /**
+     * Returns a forward history list
+     */
+    public Vector getForwardHistory();
+    
+    /**
+     * Sets the current history entry
+     *
+     * @param index The index of history entry
+     */
+    public void setHistoryEntry(int index);
+    
+    /**
+     * Removes entries related to removed HelpSet from history
+     *
+     * @param hs The removed HelpSet
+     */
+    public void removeHelpSet(HelpSet hs);
+    
+    /**
+     * Returns a history
+     */
+    public Vector getHistory();
+    
+    /**
+     * Returns a current history position
+     *
+     * @return The history index
+     */
+    public int getIndex();
+    
+    /**
+     * Sets the HelpModel
+     *
+     * @param model The HeplModel
+     */
+    public void setHelpModel(HelpModel model);
+    
+
+}
+
diff --git a/jhMaster/JavaHelp/src/new/javax/help/HelpModel.java b/jhMaster/JavaHelp/src/new/javax/help/HelpModel.java
new file mode 100644
index 0000000000000000000000000000000000000000..6b49da0bfa51a3101e6bc92a123fc5f85039c7f9
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/HelpModel.java
@@ -0,0 +1,146 @@
+/*
+ * @(#)HelpModel.java	1.27 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help;
+
+import java.net.URL;
+import java.util.Vector;
+import java.util.Enumeration;
+import javax.help.event.*;
+import javax.help.Map.ID;
+import java.beans.*;
+
+/**
+ * The interface to the model of a JHelp that represents the 
+ * HelpSet being presented to the user.
+ * 
+ * Note that a HelpSet can contain nested HelpSets within it; IDs
+ * include both a String and the HelpSet to which the String applies.
+ *
+ * @author Roger D. Brinkley
+ * @author Eduardo Pelegri-Llopart
+ * @author Richard Gregor
+ * @version   1.27     10/30/06
+ */
+public interface HelpModel {
+    /**
+     * Sets the loaded (aka "top") HelpSet for this model.
+     */
+    public void setHelpSet(HelpSet hs);
+
+    /**
+     * Gets the loaded (aka "top") HelpSet for this model.
+     */
+    public HelpSet getHelpSet();
+
+    /**
+     * Sets the current ID relative to some HelpSet
+     * HelpModelListeners and HelpVisitListeners are notified
+     *
+     * @param id the ID used to set
+     * @exception InvalidHelpSetContextException The HelpSet of the ID is not
+     * valid for the HelpSet currently loaded in the model
+     */
+    public void setCurrentID(ID id) throws InvalidHelpSetContextException;
+
+    /**
+     * Sets the current ID relative to some HelpSet
+     * HelpModelListeners and HelpVisitListeners are notified
+     *
+     * @param id the ID used to set
+     * @param historyName The name for history storage
+     * @param navigator The JHelpNavigator
+     * @exception InvalidHelpSetContextException The HelpSet of the ID is not
+     * valid for the HelpSet currently loaded in the model
+     */
+    public void setCurrentID(ID id, String historyName, JHelpNavigator navigator) throws InvalidHelpSetContextException;
+    
+    /**
+     * Gets the current ID.
+     *
+     * @return The current ID.
+     */
+    public ID getCurrentID();
+
+    /**
+     * Sets the current URL. 
+     * HelpModelListeners are notified.
+     * The current ID changes if there is a matching id for this URL
+     *
+     * @param The URL to set.
+     */
+    public void setCurrentURL(URL url);
+
+    /**
+     * Sets the current URL and the name wich will appear in history list.
+     * HelpModelListeners are notified.
+     * The current ID changes if there is a matching id for this URL
+     *
+     * @param url The URL to set.
+     * @param historyName The name to set for history
+     * @param navigator The JHelpNavigator
+     */
+    public void setCurrentURL(URL url, String historyName, JHelpNavigator navigator);
+    
+    /**
+     * Returns The current URL.
+     *
+     * @return The current URL.
+     */
+    public URL getCurrentURL();
+
+    /**
+     * Adds a listener for the HelpModelEvent posted after the model has
+     * changed.
+     * 
+     * @param l The listener to add.
+     * @see javax.help.HelpModel#removeHelpModelListener
+     */
+    public void addHelpModelListener(HelpModelListener l);
+
+    /**
+     * Removes a listener previously added with <tt>addHelpModelListener</tt>
+     *
+     * @param l The listener to remove.
+     * @see javax.help.HelpModel#addHelpModelListener
+     */
+    public void removeHelpModelListener(HelpModelListener l);
+
+    /**
+     * Adds a listener to monitor changes to the properties in this model
+     *
+     * @param l  The listener to add.
+     */
+    public void addPropertyChangeListener(PropertyChangeListener l);
+
+    /**
+     * Removes a listener monitoring changes to the properties in this model
+     *
+     * @param l  The listener to remove.
+     */
+    public void removePropertyChangeListener(PropertyChangeListener l);
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/HelpSet.java b/jhMaster/JavaHelp/src/new/javax/help/HelpSet.java
new file mode 100644
index 0000000000000000000000000000000000000000..ee551031b9908337f676d75b262d22dbadd5ebed
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/HelpSet.java
@@ -0,0 +1,1917 @@
+/*
+ * @(#)HelpSet.java	1.108 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help;
+
+import java.net.URL;
+import java.net.URLConnection;
+import java.net.MalformedURLException;
+import java.util.*;
+import java.io.*;
+import java.awt.Dimension;
+import java.awt.Point;
+import javax.help.event.EventListenerList;
+import javax.help.DefaultHelpBroker;
+import javax.help.event.HelpSetListener;
+import javax.help.event.HelpSetEvent;
+import javax.help.Map.ID;
+
+// implementation-specific
+import com.sun.java.help.impl.Parser;
+import com.sun.java.help.impl.ParserListener;
+import com.sun.java.help.impl.ParserEvent;
+import com.sun.java.help.impl.Tag;
+import com.sun.java.help.impl.TagProperties;
+import com.sun.java.help.impl.XmlReader;
+import com.sun.java.help.impl.LangElement;
+import javax.help.Map.ID;
+import java.beans.PropertyChangeSupport;
+import java.lang.reflect.Constructor;
+/**
+ * A HelpSet  is a collection of help information consisting of a HelpSet
+ * file, table of contents (TOC), index, topic files, and Map file.
+ * The HelpSet file is the portal to the HelpSet.
+ *
+ * @author Roger D. Brinkley
+ * @author Eduardo Pelegri-Llopart
+ * @author Stepan Marek
+ * @version	1.108	10/30/06
+ */
+
+public class HelpSet implements Serializable{
+    private static String errorMsg = null;
+    /*
+     * Event listeners for adding to the HelpSet
+     */
+
+    protected EventListenerList listenerList = new EventListenerList();
+
+    /**
+     * PublicID (known to this XML processor) to the DTD for version 1.0 of the HelpSet
+     */
+    public static final String publicIDString =
+        "-//Sun Microsystems Inc.//DTD JavaHelp HelpSet Version 1.0//EN";
+
+    /**
+     * PublicID (known to this XML processor) to the DTD for version 2.0 of the HelpSet
+     */
+    public static final String publicIDString_V2 =
+        "-//Sun Microsystems Inc.//DTD JavaHelp HelpSet Version 2.0//EN";
+
+    /**
+     * Information for implementation customization.
+     * 
+     * helpBroker/class is used to locate the class for a HelpBroker.
+     * helpBroker/loader is used to determine the ClassLoader to use.
+     */
+
+    public static final Object implRegistry =
+        new StringBuffer("HelpSet.implRegistry");
+    public static final String helpBrokerClass = "helpBroker/class";
+    public static final String helpBrokerLoader = "helpBroker/loader";
+
+    /**
+     * HelpSet context information.
+     *
+     * A HelpSet can map between keys (String) and values (Strings).
+     * There is a per-HelpSet value and a default value.
+     * The per-HelpSet value is specified in the appropriate section of the
+     * HelpSet file.
+     * The default value is global and only specified at class initialization time.
+     */
+
+    public static final Object kitTypeRegistry = 
+        new StringBuffer("JHelpViewer.kitTypeRegistry");
+    public static final Object kitLoaderRegistry = 
+        new StringBuffer("JHelpViewer.kitLoaderRegistry");
+
+    /**
+     * Creates an empty HelpSet that one can parse into.
+     * @param loader The ClassLoader to use. If loader is null, the default
+     * ClassLoader is used.
+     */
+    public HelpSet(ClassLoader loader) {
+	this.helpsets = new Vector();
+	this.loader = loader;
+    }
+
+    /**
+     * Creates an empty HelpSet. Uses the default ClassLoader
+     */
+    public HelpSet() {
+	this.helpsets = new Vector();
+	this.loader = null;
+    }
+
+    /**
+     * Creates a HelpSet.  The locale for the data is either that indicated in
+     * the <tt>lang</tt> attribute of the <tt>helpset</tt> tag, or
+     * <tt>Locale.getDefault()</tt> if the <tt>lang</tt> attribute is not present.
+     *
+     * @param loader The class loader to use to locate any classes
+     * required by the navigators in the Helpset
+     * If loader is null, the default ClassLoader is used.
+     * @param helpset The URL to the HelpSet "file"
+     *
+     * @exception HelpSetException if there are problems parsing the helpset
+     */
+    public HelpSet(ClassLoader loader, URL helpset) throws HelpSetException {
+	this(loader);
+	this.helpset = helpset;	// so it can be used in parseInto()
+
+	HelpSetFactory factory = new DefaultHelpSetFactory();
+
+	parseInto(helpset, factory);
+	HelpSet x = factory.parsingEnded(this); // use the error reporting
+
+	if (x == null) {
+	    // We had trouble parsing
+	    // May need to revisit this...
+            throw new HelpSetException("Could not parse\n"+errorMsg);
+	}
+    }
+
+
+    /**
+     * Locates a HelpSet file and return its URL.
+     * Applies localization conventions.
+     *
+     * @param cl The classloader to use when searching for the resource
+     * with the appropriate name. If cl is null the default 
+     * ClassLoader is used.
+     * @param shortName The shortname of the resource.
+     * @param extension The extension of the resource.
+     * @param locale The desired Locale
+     * @see javax.help.HelpUtilities
+     */
+
+    public static URL findHelpSet(ClassLoader cl,
+				  String shortName,
+				  String extension,
+				  Locale locale) {
+	// Test for whether URL can be opened! - workaround Browser bugs
+	return HelpUtilities.getLocalizedResource(cl,
+						  shortName,
+						  extension,
+						  locale,
+						  true);
+    }
+
+    /**
+     * Locates a HelpSet file and return its URL.
+     *
+     * If the name does not end with the ".hs" extension, the
+     * ".hs" extension is appended and localization rules
+     * are applied to it.
+     *
+     * @param cl The classloader to use. If cl is null the default 
+     * ClassLoader is used.
+     * @param name The name of the resource.
+     * @param locale The desired locale.
+     */
+    public static URL findHelpSet(ClassLoader cl,
+                                 String name,
+                                 Locale locale) {
+	String shortName;
+	String extension;
+	if (name.endsWith(".hs")) {
+	    shortName = name.substring(0, name.length()-3);
+	    extension = ".hs";
+	} else {
+	    shortName = name;
+	    extension = ".hs";
+	}
+	return findHelpSet(cl, shortName, extension, locale);
+    }
+
+    /**
+     * As above but default on locale to Locale.getDefault()
+     *
+     * @param cl The ClassLoader to use. If cl is null the default 
+     * ClassLoader is used.
+     * @param name The name of the resource.
+     * @return Null if not found.
+     */
+    public static URL findHelpSet(ClassLoader cl,
+                                 String name) {
+	return findHelpSet(cl, name, Locale.getDefault());
+    }
+
+
+    /**
+     * Creates a presentation object for this HelpSet.
+     * Consults the <tt>implRegistry</tt> of <tt>KeyData</tt> for 
+     * the class name (as helpBrokerClass) and for the ClassLoader 
+     * instance (as helpBrokerLoader) and then tries to instantiate 
+     * that class.  It then invokes <tt>setHelpSet()</tt> with
+     * this instance of HelpSet as the argument.  The resulting object is  
+     * returned.
+     * @see createHelpBroker(String)
+     */
+    public HelpBroker createHelpBroker() {
+	return createHelpBroker(null);
+    }
+
+    /**
+     * Creates a presentation object for this HelpSet.
+     * Consults the <tt>implRegistry</tt> of <tt>KeyData</tt> for 
+     * the class name (as helpBrokerClass) and for the ClassLoader 
+     * instance (as helpBrokerLoader) and then tries to instantiate 
+     * that class.  It then invokes <tt>setHelpSet()</tt> with
+     * this instance of HelpSet as the argument.  The resulting object is  
+     * returned.
+     * @param presenationName A presentation name defined in the HelpSet 
+     *                        that will dictate the presentation.
+     * @return HelpBroker The created HelpBroker
+     * @since 2.0
+     * @see createHelpBroker()
+     */
+    public HelpBroker createHelpBroker(String presentationName) {
+        HelpBroker back = null;
+
+	String classname =
+	    (String) getKeyData(implRegistry, helpBrokerClass);
+	ClassLoader loader =
+	    (ClassLoader) getKeyData(implRegistry, helpBrokerLoader);
+
+	if (loader == null) {
+	    loader = getLoader();
+	}
+	try {
+	    Class c;
+	    if (loader != null) {
+		c = loader.loadClass(classname);
+	    } else {
+		c = Class.forName(classname);
+	    }
+	    back = (HelpBroker) c.newInstance();
+	} catch (Throwable e) {
+	    back = null;
+	}
+
+        if (back != null) {
+            back.setHelpSet(this);
+	    HelpSet.Presentation hsPres = null;
+	    // If there is a presentation name find it otherwise get the
+	    // default if one exists.
+	    if (presentationName != null) {
+		hsPres = getPresentation(presentationName);
+	    } else {
+		hsPres = getDefaultPresentation();
+	    }
+	    if (hsPres != null) {
+		back.setHelpSetPresentation(hsPres);
+	    }
+	}
+        return back;
+    }
+
+    /**
+     * Adds a HelpSet, HelpSetEvents are generated.
+     * Adding a composed HelpSet to another is equivalent to
+     * adding all the HelpSets individually.
+     *
+     * @param hs The HelpSet to add.
+     */
+    public void add(HelpSet hs) {
+	debug("add("+hs+")");
+	helpsets.addElement(hs);
+	fireHelpSetAdded(this, hs);
+	combinedMap = null;	// invalidate the map
+    }
+
+    /**
+     * Removes a HelpSet from this HelpSet; HelpSetEvents are generated
+     * Return True if it is found, otherwise false.
+     *
+     * @param hs The HelpSet to remove. 
+     * @return False if the hs is null or was not in this HelpSet
+     */
+    public boolean remove(HelpSet hs) {
+	if (helpsets.removeElement(hs)) {
+	    fireHelpSetRemoved(this, hs);
+	    combinedMap = null;	// HERE - invalidate it - epll
+	    return true;
+	} else {
+	    return false;
+	}
+    }
+
+    /**
+     * Enumerates all the HelpSets that have been added to this one.
+     *
+     * @return An enumeration of the HelpSets that have been added to
+     * this HelpSet.
+     */
+    public Enumeration getHelpSets() {
+	return helpsets.elements();
+    }
+
+    /**
+     * Determines if a HelpSet is a sub-HelpSet of this object.
+     *
+     * @param hs The HelpSet to check
+     * @return true If <tt>hs</tt> is contained in this HelpSet or in one of its children.
+     */
+    public boolean contains(HelpSet hs) {
+	if (hs == this) {
+	    return true;
+	}
+	for (Enumeration e = helpsets.elements();
+	     e.hasMoreElements();) {
+	    HelpSet child = (HelpSet) e.nextElement();
+	    if (child.contains(hs)) {
+		return true;
+	    }
+	}
+	return false;
+    }
+
+    /**
+     * Adds a listener for the HelpSetEvent posted after the model has
+     * changed.
+     * 
+     * @param l - The listener to add.
+     * @see javax.help.HelpSet#removeHelpSetListener. 
+     * @throws IllegalArgumentException if l is null.
+     */
+    public void addHelpSetListener(HelpSetListener l) {
+	debug("addHelpSetListener("+l+")");
+	listenerList.add(HelpSetListener.class, l);
+    }
+
+    /**
+     * Removes a listener previously added with <tt>addHelpSetListener</tt>
+     *
+     * @param l - The listener to remove.
+     * @see javax.help.HelpSet#addHelpSetListener. 
+     * @throws IllegalArgumentException if l is null.
+     */
+    public void removeHelpSetListener(HelpSetListener l) {
+	listenerList.remove(HelpSetListener.class, l);
+    }
+
+    /**
+     * Fires a helpSetAdded event.
+     */
+    protected void fireHelpSetAdded(Object source, HelpSet helpset){
+	Object[] listeners = listenerList.getListenerList();
+	HelpSetEvent e = null;
+
+	for (int i = listeners.length - 2; i >= 0; i -= 2) {
+	    if (listeners[i] == HelpSetListener.class) {
+		if (e == null) {
+		    e = new HelpSetEvent(this, helpset,
+					 HelpSetEvent.HELPSET_ADDED);
+		}
+		((HelpSetListener)listeners[i+1]).helpSetAdded(e);
+	    }	       
+	}
+    }
+
+    /**
+     * Fires a helpSetRemoved event.
+     */
+    protected void fireHelpSetRemoved(Object source, HelpSet helpset){
+	Object[] listeners = listenerList.getListenerList();
+	HelpSetEvent e = null;
+
+	for (int i = listeners.length - 2; i >= 0; i -= 2) {
+	    if (listeners[i] == HelpSetListener.class) {
+		if (e == null) {
+		    e = new HelpSetEvent(this, helpset,
+					 HelpSetEvent.HELPSET_REMOVED);
+		}
+		((HelpSetListener)listeners[i+1]).helpSetRemoved(e);
+	    }	       
+	}
+    }
+
+    // ======= Labels, etc =======
+    /**
+     * Gets the title of this HelpSet.
+     *
+     * @return the title
+     */
+    public String getTitle() {
+	if (title == null) {
+	    return "";
+	} else {
+	    return title;
+	}
+    }
+
+    /**
+     * Sest the title for this HelpSet.  This is a bound property.
+     *
+     * @param title The title to set.
+     */
+    
+    public void setTitle(String title) {
+	String oldTitle = this.title;
+	this.title = title;
+	changes.firePropertyChange("title", oldTitle, title);
+    }
+
+    /**
+     * Gets the locale for this HelpSet.
+     * 
+     * @return The locale.
+     */
+    public Locale getLocale() {
+	return locale;
+    }
+
+    /**
+     * Sets the locale for this HelpSet.
+     * Strictly a private routine but the read-only property is bound.
+     *
+     * @param locale The locale to set.
+     */
+    private void setLocale(Locale l) {
+	Locale oldLocale = locale;
+	locale = l;
+	changes.firePropertyChange("locale", oldLocale, locale);
+    }
+
+    /**
+     * Returns 
+     * the ID to visit when the user makes a "go home" gesture.
+     * This can be identified in the project file, but may also be changed
+     * programmatically or (possibly) via the UI.
+     * 
+     * @return The ID of home. A null is returned if homeID is null
+     * or if an ID cannot be created for the homeID.
+     */
+    public ID getHomeID() {
+	if (homeID == null) {
+	    return null;
+	} else {
+	    try {
+		return ID.create(homeID, this);
+	    } catch (Exception ex) {
+		return null;
+	    }
+	}
+    }
+
+    /**
+     * Sets the Home ID for a HelpSet.  This is a bound property.
+     *
+     * @param The ID (in the Map) that identifies the default topic for this HelpSet. Null is valid homeID.
+     */
+    public void setHomeID(String homeID) {
+	String oldID = homeID;
+	this.homeID = homeID;
+	changes.firePropertyChange("homeID", oldID, homeID);
+    }
+
+    // WARNING/HERE: In this implementation, the Map is not updated automatically
+    // so you need to come get a new one - epll
+
+    // Warning.  This is not handling recursive aggregation
+
+    /**
+     * The map for this HelpSet.  This map involves the closure of 
+     * this HelpSet's children HelpSets.
+     *
+     * @return The map
+     */
+    public Map getCombinedMap() {
+ 	if (combinedMap == null) {
+ 	    combinedMap = new TryMap();
+	    if (map != null) {
+		combinedMap.add(map); // the local map
+	    }
+	    for (Enumeration e = helpsets.elements();
+		 e.hasMoreElements(); ) {
+		HelpSet hs = (HelpSet) e.nextElement();
+		combinedMap.add(hs.getCombinedMap());
+	    }
+	}
+	return combinedMap;
+    }
+
+    /**
+     * Get the local (i.e.<!-- --> non-recursive) Map for this HelpSet.
+     * This Map does not include the Maps for its children.
+     *
+     * @return The Map object that associates ID->URL. A null map is valid.
+     */
+    public Map getLocalMap() {
+	return this.map;
+    }
+
+    /**
+     * Set the Map for this HelpSet.  This Map object is not recursive; for example,
+     * it does not include the Maps for its children.
+     *
+     * @param The Map object that associates ID->URL. A null map is a valid.
+     */
+    public void setLocalMap(Map map) {
+	this.map = map;
+    }
+
+    /**
+     * The URL that is the base for this HelpSet.
+     *
+     * @return The URL that is base to this HelpSet.
+     */
+    public URL getHelpSetURL() {
+	return helpset;
+    }
+
+    /**
+     * A classloader to use when locating classes.
+     *
+     * @return The ClassLoader to use when locating classes mentioned
+     * in this HelpSet.
+     */
+
+    public ClassLoader getLoader() {
+	return loader;
+    }
+
+    /**
+     * NavigatorView describes the navigator views that are requested
+     * by this HelpSet.
+     *
+     * @return The array of NavigatorView.
+     */
+
+    public NavigatorView[] getNavigatorViews() {
+	NavigatorView back[] = new NavigatorView[views.size()];
+	views.copyInto(back);
+	return back;
+    }
+
+    /**
+     * Gets the NavigatorView with a specific name.
+     *
+     * @param The name of the desired navigator view.
+     */
+    public NavigatorView getNavigatorView(String name) {
+	debug("getNavigatorView("+name+")");
+	for (int i=0; i<views.size(); i++) {
+	    NavigatorView view = (NavigatorView) views.elementAt(i);
+	    if (view.getName().equals(name)) {
+		debug("  = "+view);
+		return view;
+	    }
+	}
+	debug("  = null");
+	return null;
+    }
+
+    /**
+     * HelpSet.Presentation describes the presentations that are defined
+     * by this HelpSet.
+     *
+     * @return The array of HelpSet.Presentations.
+     */
+
+    public HelpSet.Presentation [] getPresentations() {
+	HelpSet.Presentation back[] = new HelpSet.Presentation[presentations.size()];
+	presentations.copyInto(back);
+	return back;
+    }
+
+    /**
+     * Gets the HelpSet.Presentation with a specific name.
+     *
+     * @param The name of the desired HelpSet.Presentation.
+     */
+    public HelpSet.Presentation getPresentation(String name) {
+	debug("getPresentation("+name+")");
+	for (int i=0; i<presentations.size(); i++) {
+	    HelpSet.Presentation pres = (HelpSet.Presentation) presentations.elementAt(i);
+	    if (pres.getName().equals(name)) {
+		debug("  = "+pres);
+		return pres;
+	    }
+	}
+	debug("  = null");
+	return null;
+    }
+
+    public HelpSet.Presentation getDefaultPresentation() {
+	return defaultPresentation;
+    }
+
+    /**
+     * Prints Name for this HelpSet.
+     */
+    public String toString() {
+	return getTitle();
+    }
+
+    // ===== Public interfaces to parsing
+
+    /**
+     * Parsed a HelpSet file.
+     */
+    public static HelpSet parse(URL url,
+				ClassLoader loader,
+				HelpSetFactory factory) {
+	HelpSet hs = new HelpSet(loader); // an empty HelpSet
+	hs.helpset = url;
+	hs.parseInto(url, factory);
+	return factory.parsingEnded(hs);
+    }
+
+    /**
+     * Parses into this HelpSet.
+     */
+    public void parseInto(URL url,
+			  HelpSetFactory factory) {
+	Reader src;
+	try {
+	    URLConnection uc = url.openConnection();
+	    src = XmlReader.createReader(uc);
+	    factory.parsingStarted(url);
+	    (new HelpSetParser(factory)).parseInto(src, this);
+	    src.close();
+	} catch (Exception ex) {
+	    factory.reportMessage("Got an IOException ("+
+				       ex.getMessage()+
+				       ")", false);
+	    if(debug)
+                ex.printStackTrace();
+	}
+
+	// Now add any subhelpsets
+	for (int i=0; i<subHelpSets.size(); i++) {
+	    HelpSet subHS = (HelpSet) subHelpSets.elementAt(i);
+	    add(subHS);
+	}
+    }
+
+    /**
+     * The default HelpSetFactory that processes HelpSets.
+     */
+
+    public static class DefaultHelpSetFactory implements HelpSetFactory {
+	private Vector messages = new Vector();
+	private URL source;
+	private boolean validParse = true;
+
+	/**
+	 * Parsing starts.
+	 */
+	public void parsingStarted(URL source) {
+	    if (source == null) {
+		throw new NullPointerException("source");
+	    }
+	    this.source = source;
+	}
+
+	/**
+	 * Process a DOCTYPE
+	 * @param publicID the document. If null or is not valid a parsingError
+	 * will be generated.
+	 */
+	public void processDOCTYPE(String root, 
+				   String publicID,
+				   String systemID) {
+	    if (publicID == null ||
+		(publicID.compareTo(publicIDString) != 0 &&
+		 publicID.compareTo(publicIDString_V2) != 0)) {
+		parsingError("helpset.wrongPublicID", publicID);
+	    }
+	}
+
+	/**
+	 * Processes a PI
+	 */
+	public void processPI(HelpSet hs,
+			      String target,
+			      String data) {
+	    // ignore for now
+	}
+
+	/**
+	 * A title is found
+	 */
+	public void processTitle(HelpSet hs,
+				 String value) {
+	    String title = hs.getTitle();
+	    if ((title != null) && !title.equals("")) {
+		parsingWarning("helpset.wrongTitle", value, title);
+	    }
+	    hs.setTitle(value);
+	}
+
+	/**
+	 * A HomeID is found.
+	 */
+
+	public void processHomeID(HelpSet hs,
+				  String value) {
+	    ID homeID = hs.getHomeID();
+	    if ((homeID == null) || homeID.equals("")) {
+		//parsingError("helpset.wrongHomeID", value, homeID.id);
+                hs.setHomeID(value);
+            }else{
+                parsingError("helpset.wrongHomeID", value, homeID.id);
+            }
+
+	}
+
+	/**
+	 * process a &lt;mapref&gt;
+	 *
+	 * @param Spec to the URL
+	 * @param Attributes for the tag
+	 */
+	public void processMapRef(HelpSet hs,
+				  Hashtable attributes) {
+	    String spec = (String) attributes.get("location");
+	    URL hsURL = hs.getHelpSetURL();
+	    try {
+		Map map = new FlatMap(new URL(hsURL, spec), hs);
+		Map omap = hs.getLocalMap();
+		if (omap == null) {
+                    debug("map is null");
+		    hs.setLocalMap(map);
+		} else {
+		    // to implement multiple Maps add this code:
+		    //
+ 		    if (omap instanceof TryMap) {
+                        debug("map is TryMap");
+		        ((TryMap)omap).add(map);
+                        ///
+                        ///what about hs.setLocalMap////
+                        ///
+                        hs.setLocalMap(omap);
+		    } else {
+                        debug("map is not TryMap");
+		        TryMap tmap = new TryMap();
+                        tmap.add(omap);
+		        tmap.add(map);
+		        hs.setLocalMap(tmap);
+		    }
+
+		}
+	    } catch (MalformedURLException ee) {
+		parsingError("helpset.malformedURL", spec);
+	    } catch (IOException ee) {
+		parsingError("helpset.incorrectURL", spec);
+	    } catch (Exception ex) {
+		// parsing error...
+	    }
+	}
+
+	/*
+	 * Called per &lt;view&gt;
+	 */
+	public void processView(HelpSet hs,
+				String name,
+				String label,
+				String type,
+				Hashtable viewAttributes,
+				String data,
+				Hashtable dataAttributes,
+				Locale locale) {
+                
+	     try {
+		 NavigatorView view;
+		 if (data != null) {
+		     if (dataAttributes == null) {
+			 dataAttributes = new Hashtable();
+		     }
+		     dataAttributes.put("data", data);
+		     
+		 }
+		 
+		 view = NavigatorView.create(hs,
+					     name, label,
+					     locale,
+					     type,
+					     dataAttributes);
+		 
+		 if (view == null) {
+		     // ignore ?? 
+		 } else {
+		     
+		     hs.addView(view);
+		 }
+	     } catch (Exception ex) {
+		 // ignore this view...
+	     }
+	}
+
+	/*
+	 * Called per &lt;presentation&gt;
+	 */
+	public void processPresentation(HelpSet hs,
+					String name,
+					boolean defaultPresentation,
+					boolean displayViews,
+					boolean displayViewImages,
+					Dimension size,
+					Point location,
+					String title,
+					String imageID,
+					boolean toolbar,
+					Vector helpActions) {
+
+	    Map.ID imageMapID = null;
+	    try {
+		imageMapID = ID.create(imageID, hs);
+	    } catch (BadIDException bex2) {
+	    } 
+	    try {
+		HelpSet.Presentation presentation = 
+		    new HelpSet.Presentation(name, displayViews, 
+					     displayViewImages, size,
+					     location, title, imageMapID, 
+					     toolbar, helpActions);
+
+		if (presentation == null) {
+		    // ignore ?? 
+		} else {
+		    hs.addPresentation(presentation, defaultPresentation);
+		}
+	    } catch (Exception ex) {
+		// ignore this presentation...
+	    }
+	}
+
+	/**
+	 * Called when a sub-HelpSet is found.
+	 */
+	public void processSubHelpSet(HelpSet hs,
+				      Hashtable attributes) {
+	    debug("createSubHelpSet");
+
+	    String spec = (String) attributes.get("location");
+	    URL base = hs.getHelpSetURL();
+	    
+	    debug("  location: "+spec);
+	    debug("  base helpset: "+base);
+	    
+	    URL u = null;
+	    HelpSet subHS = null;
+	    try {
+		u = new URL(base, spec);
+		// test and see if the file is there
+		// if it doesnt' through an exception all is ok
+		InputStream is = u.openStream();
+		if (is != null) {
+		    subHS = new HelpSet(hs.getLoader(), u);
+		    if (subHS != null) {
+			hs.addSubHelpSet(subHS);
+		    }
+		}
+	    } catch (MalformedURLException ex) {
+		// ignore a malformed URL
+		// The subhelpset is just ignored
+	    } catch (IOException ex) {
+		// ignore an IOException
+		// The subhelpset is just ignored
+	    } catch (HelpSetException ex) {
+		parsingError("helpset.subHelpSetTrouble", spec);
+	    }
+	}
+
+	/**
+	 * Reports an error message.
+	 */
+	public void reportMessage(String msg, boolean validParse) {
+	    messages.addElement(msg);
+	    this.validParse = this.validParse && validParse;
+	}
+
+	/**
+	 * Enumerates all the error messages.
+	 */
+	public Enumeration listMessages() {
+	    return messages.elements();
+	}
+
+	/**
+	 * Parsing has ended. Last chance to do something
+	 * to the HelpSet.
+	 * @param hs The HelpSet the parsing ended on. A null hs is valid.
+	 */
+	public HelpSet parsingEnded(HelpSet hs) {
+	    HelpSet back = hs;
+	    if (! validParse) {
+		// A parse with problems...
+		back = null;
+
+                String errMsg = "Parsing failed for "+source;
+                //System.err.println(errMsg);
+                messages.addElement(errMsg);
+
+		for (Enumeration e = messages.elements();
+		     e.hasMoreElements();) {
+		    String msg = (String) e.nextElement();
+                    if(debug)
+                        System.err.println(msg);                        
+                    if(HelpSet.errorMsg == null)
+                        HelpSet.errorMsg = msg;
+                    else{
+                       HelpSet.errorMsg = HelpSet.errorMsg+"\n"; 
+                       HelpSet.errorMsg = HelpSet.errorMsg + msg;
+                    }
+
+		}
+	    }
+	    return back;
+	}
+
+	// Convenience methods
+	private void parsingError(String key) {
+	    String s = HelpUtilities.getText(key);
+	    reportMessage(s, false); // tree will be wrong
+	}
+
+	/**
+	 * @throws Error if key is invalid.
+	 */
+	private void parsingError(String key, String s) {
+	    String msg = HelpUtilities.getText(key, s);
+	    reportMessage(msg, false); // tree will be wrong
+	}
+
+	/**
+	 * @throws Error if key is invalid.
+	 */
+	private void parsingError(String key, String s1, String s2) {
+	    String msg = HelpUtilities.getText(key, s1, s2);
+	    reportMessage(msg, false); // tree will be wrong
+	}
+
+	private void parsingWarning(String key, String s1, String s2) {
+	    String msg = HelpUtilities.getText(key, s1, s2);
+	    reportMessage(msg, true); // warning only
+	}
+
+    } // End of DefaultHelpSetFactory
+
+
+    /**
+     * HelpSet Presentation class. Contains information concerning a
+     * presentation in a HelpSet file
+     * @since 2.0
+     */
+    public static class Presentation {
+
+	private String name;
+	private boolean displayViews;
+	private boolean displayViewImages;
+	private Dimension size;
+	private Point location;
+	private String title;
+	private boolean toolbar;
+	private Vector helpActions;
+	private Map.ID imageID;
+
+	public Presentation (String name,
+			     boolean displayViews,
+			     boolean displayViewImages,
+			     Dimension size,
+			     Point location,
+			     String title,
+			     Map.ID imageID,
+			     boolean toolbar,
+			     Vector helpActions) {
+	    this.name = name;
+	    this.displayViews = displayViews;
+	    this.displayViewImages = displayViewImages;
+	    this.size = size;
+	    this.location = location;
+	    this.title = title;
+	    this.imageID = imageID;
+	    this.toolbar = toolbar;
+	    this.helpActions = helpActions;
+	}
+
+	public String getName() {
+	    return name;
+	}
+
+	public String getTitle() {
+	    return title;
+	}
+
+	public Map.ID getImageID() {
+	    return imageID;
+	}
+
+	public boolean isViewDisplayed() {
+	    return displayViews;
+	}
+	
+	public boolean isViewImagesDisplayed() {
+	    return displayViewImages;
+	}
+	
+	public Dimension getSize() {
+	    return size;
+	}
+
+	public Point getLocation() {
+	    return location;
+	}
+
+	public boolean isToolbar() {
+	    return toolbar;
+	}
+
+	/**
+	 * Returns an Enumeration HelpActions created from the
+	 * list of Actions in the Presentation.
+	 *
+	 * @see HelpAction
+	 */
+	public Enumeration getHelpActions(HelpSet hs, Object control) {
+	    Vector actions = new Vector();
+	    ClassLoader loader = hs.getLoader();
+	    Class klass;
+	    Constructor konstructor;
+	    HelpAction action;
+
+	    if (helpActions == null) {
+		// got a nutziod who didn't check the isToolbar
+		// just return back the empty vector elements
+		return actions.elements();
+	    }
+	    Enumeration actionEnum = helpActions.elements();
+	    while (actionEnum.hasMoreElements()) { 
+		HelpSetFactory.HelpAction act = 
+		    (HelpSetFactory.HelpAction)actionEnum.nextElement();
+
+		try {
+		    Class types[] = { Object.class };
+		    Object args[] = { control };
+		    if (loader == null) {
+			klass = Class.forName(act.className);
+		    } else {
+			klass = loader.loadClass(act.className);
+		    }
+		    konstructor = klass.getConstructor(types);
+		    action = (HelpAction) konstructor.newInstance(args);
+
+		    // The HelpAction has been added now add any known
+		    // attributes
+		    if (act.attr.containsKey("image")) {
+			String imageID = (String) act.attr.get("image");
+			try {
+			    Map.ID id = Map.ID.create(imageID, hs);
+			    javax.swing.ImageIcon icon = null;
+			    Map map = hs.getCombinedMap();
+			    URL url = map.getURLFromID(id);
+			    icon = new javax.swing.ImageIcon(url);
+			    action.putValue("icon", icon);
+			} catch (Exception ex) {
+			}
+		    }
+		    actions.add(action);
+		} catch (Exception ex) {
+		    throw new RuntimeException("Could not create HelpAction " +
+					       act.className);
+		}
+	    }
+	    
+	    return actions.elements();
+	}
+
+    }
+
+    // =========== Protected Methods for use by subclasses ==========
+
+    /**
+     * Adds a NavigatorView to the current list.
+     */
+    protected void addView(NavigatorView view) {
+	views.addElement(view);
+    }
+
+    /**
+     * Adds a SubHelpSet to the current list.
+     */
+
+    protected void addSubHelpSet(HelpSet hs) {
+	subHelpSets.addElement(hs);
+    }
+
+    /**
+     * Adds a HelpSet.Presentation to the current list.
+     */
+    protected void addPresentation(HelpSet.Presentation presentation,
+				   boolean defaultPres) {
+	presentations.addElement(presentation);
+	if (defaultPres) {
+	    defaultPresentation = presentation;
+	}
+    }
+
+    // ============= Simple registry ============
+
+    /**
+     * Gets some Data for a Key in a given context.
+     * Local (per HelpSet instance) data is searched first, then defaults.
+     */
+      
+    public Object getKeyData(Object context,
+			     String key) {
+	Object back = null;
+	Hashtable h = (Hashtable) localKeys.get(context);
+	if (h != null) {
+	    back = h.get(key);
+	}
+	if (back == null) {
+	    h = (Hashtable) defaultKeys.get(context);
+	    if (h != null) {
+		back = h.get(key);
+	    }
+	}
+	return back;
+    }
+
+    /**
+     * Sets some local KeyData on a given context.  The information is set on
+     * a per-HelpSet basis.
+     */
+    public void setKeyData(Object context,
+			   String key,
+			   Object data) {
+	Hashtable h = (Hashtable) localKeys.get(context);
+	if (h == null) {
+	    h = new Hashtable();
+	    localKeys.put(context, h);
+	}
+	h.put(key, data);
+    }
+
+    /**
+     * Default initialization.  This can only be done from within this class.
+     */
+    private static void setDefaultKeyData(Object context,
+					  String key,
+					  Object data) {
+	if (defaultKeys == null) {
+	    defaultKeys = new Hashtable();
+	}
+	Hashtable h = (Hashtable) defaultKeys.get(context);
+	if (h == null) {
+	    h = new Hashtable();
+	    defaultKeys.put(context, h);
+	}
+	h.put(key, data);
+    }
+
+
+    /**
+     * Initializes the default registries.
+     */
+    static {
+        setDefaultKeyData(implRegistry,
+			  helpBrokerClass, "javax.help.DefaultHelpBroker");
+	setDefaultKeyData(kitTypeRegistry,
+			  "text/html", "com.sun.java.help.impl.CustomKit");
+
+	ClassLoader cl = HelpSet.class.getClassLoader();
+	if (cl != null) {
+	    setDefaultKeyData(implRegistry,
+			      helpBrokerLoader, cl);
+	    setDefaultKeyData(kitLoaderRegistry,
+			      "text/html", cl);
+	}
+    }
+
+    //======== Private members =========
+
+    private String title;	// the title for this helpset
+    private Map map;		// the local map
+    private TryMap combinedMap;	// the combined ID<->URL map
+    private URL helpset;	// the HelpSet from where to search
+    private String homeID;
+    private Locale locale = Locale.getDefault();
+
+    private transient ClassLoader loader;	// encapsulates loading...
+
+    private Vector views = new Vector();
+
+    private Vector presentations = new Vector();
+
+    private HelpSet.Presentation defaultPresentation = null;
+
+    private Vector helpsets;	// All the helpsets added to this one
+
+    private static HelpBroker defaultHelpBroker = null; // the default HelpBroker
+
+    private Vector subHelpSets = new Vector();
+
+    // Default and Local Hashtables for keys
+
+    private static Hashtable defaultKeys;
+    private Hashtable localKeys = new Hashtable();
+
+    private PropertyChangeSupport changes = new PropertyChangeSupport(this);
+
+    // ============= PRIVATE Parsing Class ========
+
+    /**
+     * Inner class for parsing a TOC stream.
+     *
+     * WARNING!! This class is an interim solution until when we move to a
+     * real XML parser.  This is not a public class.  Clients should only use
+     * the parse method in the enclosing class.
+     */
+
+    private static class HelpSetParser implements ParserListener {
+	private Stack tagStack;	// the collection of active Parse tags
+	private Locale defaultLocale;
+	private Locale lastLocale;
+	private HelpSet myHS;	// my HelpSet
+	private Locale myHSLocale; // its locale
+	private HelpSetFactory factory;	// the factory
+
+
+	private String tagName;	  // genericly used for views and presentation 
+	private String viewLabel;
+	private String viewType;
+	private String viewEngine;
+        private String tagImage;
+        private String helpActionImage;
+	private String viewData;
+        private String viewMergeType;
+	private Hashtable htData;
+
+	private boolean defaultPresentation = false;
+	private boolean displayViews = true;
+	private boolean displayViewImages = true;
+	private Dimension size;
+	private Point location;
+	private String presentationTitle;
+	private boolean toolbar;
+	private Vector helpActions;
+	private String helpAction;
+
+	/**
+	 * Creates a Parser (Listener) instance.
+	 */
+	HelpSetParser (HelpSetFactory factory) {
+	    this.factory = factory;
+	}
+
+	/**
+	 * Parses a reader into a HelpSet.
+	 */
+	synchronized void parseInto(Reader src,
+				    HelpSet hs) 
+	    throws IOException
+        {
+	    tagStack = new Stack();
+	    defaultLocale = hs.getLocale();
+	    lastLocale = defaultLocale;
+	    myHS = hs;
+	    myHSLocale = hs.getLocale();
+	    Parser parser = new Parser(src); // the XML parser instance
+	    parser.addParserListener(this);
+	    parser.parse();
+	}
+
+	public void tagFound(ParserEvent e) {
+            debug("tagFound " + e.getTag().name);
+	    Locale locale = null;
+	    LangElement le;
+	    Tag tag = e.getTag();
+	    String name = tag.name;
+	    int x=0, y=0, width=0, height=0;
+	    TagProperties attr = tag.atts;
+	    Hashtable ht = (attr == null) ? null : attr.getHashtable();
+
+	    if (attr != null) {
+		String lang = attr.getProperty("xml:lang");
+		locale = HelpUtilities.localeFromLang(lang);
+                viewMergeType = attr.getProperty("mergetype");
+		helpActionImage = attr.getProperty("image");
+		String value = null;
+		value = attr.getProperty("width");
+		if (value != null) {
+		    width = Integer.parseInt(value);
+		}
+		value = null;
+		value = attr.getProperty("height");
+		if (value != null) {
+		    height = Integer.parseInt(value);
+		}
+		value = null;
+		value = attr.getProperty("x");
+		if (value != null) {
+		    x = Integer.parseInt(value);
+		}
+		value = null;
+		value = attr.getProperty("y");
+		if (value != null) {
+		    y = Integer.parseInt(value);
+		}
+		value = null;
+		value = attr.getProperty("default");
+		if (value != null && value.equals("true")) {
+		    defaultPresentation = true;
+		}
+		value = null;
+		value = attr.getProperty("displayviews");
+		if (value != null && value.equals("false")) {
+		    displayViews = false;
+		}
+		value = null;
+		value = attr.getProperty("displayviewimages");
+		if (value != null && value.equals("false")) {
+		    displayViewImages = false;
+		}
+	    }
+	    if (locale == null) {
+		locale = lastLocale;
+	    }
+            
+	    if (name.equals("helpset")) {
+		if (tag.isEnd) {
+		    removeTag(tag);
+		} else {
+		    // Check and see if the locale is different from the
+		    // defaultLocale. If it is then reset the locale.
+ 		    if (! locale.equals(defaultLocale) &&
+			! locale.equals(myHSLocale)) {
+			if (locale != null) {
+			    myHS.setLocale(locale);
+			    defaultLocale = locale;
+			}
+		    }
+		    if (attr != null) {
+		        String version = attr.getProperty("version");
+			if (version != null && 
+			    (version.compareTo("1.0") != 0 &&
+			     version.compareTo("2.0") != 0)) {
+			    parsingError("helpset.unknownVersion", version);
+			}
+		    }
+		    addTag(tag, locale);
+		}
+		return;
+	    }
+
+	    if (tagStack.empty()) {
+		parsingError("helpset.wrongTopLevel", name);
+	    }
+
+	    // Get the parents name
+	    le = (LangElement) tagStack.peek();
+	    String pname = ((Tag) le.getTag()).name; // the parent
+
+	    if (name.equals("title")) {
+		// TITLE tag
+		if (tag.isEnd) {
+		    removeTag(tag);		// processing was done in textFound()
+		} else {
+		    if ((! pname.equals("helpset")) &&
+			(! pname.equals("presentation"))){
+			wrongParent(name, pname);
+		    }
+ 		    if (! locale.equals(defaultLocale) &&
+			! locale.equals(myHSLocale)) {
+			wrongLocale(locale, defaultLocale, myHSLocale);
+		    }
+		    addTag(tag, locale);
+		}
+	    } else if (name.equals("homeID")) {
+		// HOMEID tags
+		if (tag.isEnd) {
+		    removeTag(tag);		// processing was done in textFound()
+		} else {
+		    if (! pname.equals("maps")) {
+			wrongParent(name, pname);
+		    }
+		    addTag(tag, locale);
+		}
+	    } else if (name.equals("mapref")) {
+		// MAPREF tags
+
+		// Remove from stack if an empty tag
+		if (tag.isEnd && !tag.isEmpty) {
+		    removeTag(tag);
+		} else {
+		    if (! pname.equals("maps")) {
+			wrongParent(name, pname);
+		    }
+		    // add the tag if not an empty tag
+		    if (! tag.isEmpty) {
+			addTag(tag, locale);
+		    }
+		    // Process the tag
+		    factory.processMapRef(myHS,
+					  ht);
+		}
+	    } else if (name.equals("data")) {
+		// DATA tag
+		if (tag.isEnd) {
+		    removeTag(tag);
+		} else {
+		    if (! pname.equals("view")) {
+			wrongParent(name, pname);
+		    } else {
+			addTag(tag, locale);
+		    }
+		    htData = ht;
+		}
+	    } else if (name.equals("name") ||
+		       name.equals("type") ||
+		       name.equals("image")){                           
+		// NAME, TYPE, IMAGE tag
+		if (tag.isEnd) {
+		    removeTag(tag);
+		} else {
+		    if ((! pname.equals("view")) && 
+			(! pname.equals("presentation"))) {
+			wrongParent(name, pname);
+		    } else {
+			addTag(tag, locale);
+		    }
+		}
+	    } else if (name.equals("label")) {
+		// LABEL tag
+		// Special processing to check the locale attribute.
+		if (tag.isEnd) {
+		    removeTag(tag);
+		} else {
+		    if (! pname.equals("view")) {
+			wrongParent(name, pname);
+		    } else {
+			if (! locale.equals(defaultLocale) &&
+			    ! locale.equals(myHSLocale)) {
+			    wrongLocale(locale, defaultLocale, myHSLocale);
+			}
+			addTag(tag, locale);
+		    }
+		}
+	    } else if (name.equals("view")) {
+		// VIEW tag
+		if (tag.isEnd) {
+		    removeTag(tag);
+
+                    if (tagImage != null) {
+                        if (htData == null) {
+                            htData = new Hashtable();
+			}
+                        htData.put("imageID", tagImage);
+                    }
+                    
+                    if (viewMergeType != null) {
+                        if(htData == null) {
+                            htData = new Hashtable();
+			}
+                        htData.put("mergetype",viewMergeType);
+                    }
+
+		    factory.processView(myHS,
+					tagName,
+					viewLabel,
+					viewType,
+					ht,
+					viewData,
+					htData,
+					locale);
+                    tagName = null;
+                    viewLabel = null;
+                    viewType = null;
+                    tagImage = null;
+                    viewData = null;
+                    htData = null;
+                    viewMergeType = null;
+
+		} else {
+		    if (! pname.equals("helpset")) {
+			wrongParent(name, pname);
+		    } else {
+			addTag(tag, locale);
+		    }
+		}
+	    } else if (name.equals("presentation")) {
+		// Presentation tag
+		if (tag.isEnd) {
+		    removeTag(tag);
+
+		    factory.processPresentation(myHS,
+						tagName,
+						defaultPresentation,
+						displayViews,
+						displayViewImages,
+						size,
+						location,
+						presentationTitle,
+						tagImage,
+						toolbar,
+						helpActions);
+
+                    tagName = null;
+                    defaultPresentation = false;
+                    displayViews = true;
+                    displayViewImages = true;
+                    size = null;
+                    location = null;
+                    presentationTitle = null;
+		    tagImage = null;
+		    toolbar = false;
+		    helpActions = null;
+
+		} else {
+		    if (! pname.equals("helpset")) {
+			wrongParent(name, pname);
+		    } else {
+			addTag(tag, locale);
+		    }
+		}
+	    } else if (name.equals("size")) {
+		// DATA tag
+		if (tag.isEnd) {
+		    if (size == null) {
+			size = new Dimension(width, height);
+		    } else {
+			size.setSize(width, height);
+		    }
+		    width = 0;
+		    height = 0;
+		    if (!tag.isEmpty) {
+			removeTag(tag);
+		    }
+		} else {
+		    if (! pname.equals("presentation")) {
+			wrongParent(name, pname);
+		    } else {
+			addTag(tag, locale);
+			size = new Dimension();
+		    }
+		}
+	    } else if (name.equals("location")) {
+		// DATA tag
+		if (tag.isEnd) {
+		    if (location == null) {
+			location = new Point(x, y);
+		    } else {
+			location.setLocation(x, y);
+		    }
+		    x = 0;
+		    y = 0;
+		    if (!tag.isEmpty) {
+			removeTag(tag);
+		    }
+		} else {
+		    if (! pname.equals("presentation")) {
+			wrongParent(name, pname);
+		    } else {
+			addTag(tag, locale);
+			location = new Point();
+		    }
+		}
+	    } else if (name.equals("toolbar")) {
+		// DATA tag
+		if (tag.isEnd) {
+		    removeTag(tag);
+		} else {
+		    if (! pname.equals("presentation")) {
+			wrongParent(name, pname);
+		    } else {
+			addTag(tag, locale);
+			helpActions = new Vector();
+			toolbar = true;
+		    }
+		}
+	    } else if (name.equals("helpaction")) {
+		// DATA tag
+		if (tag.isEnd) {
+		    removeTag(tag);
+		    if (helpAction != null) {
+			Hashtable tmp = new Hashtable();		      
+			helpActions.add(new HelpSetFactory.HelpAction(helpAction, tmp));
+			if (helpActionImage != null) {
+			    tmp.put("image", helpActionImage);
+			    helpActionImage = null;
+			}
+			helpAction = null;
+		    }
+		} else {
+		    if (! pname.equals("toolbar")) {
+			wrongParent(name, pname);
+		    } else {
+			addTag(tag, locale);
+		    }
+		}
+	    } else if (name.equals("maps")) {
+		// MAPS tag
+		if (tag.isEnd) {
+		    removeTag(tag);
+		} else {
+		    if (! pname.equals("helpset")) {
+			wrongParent(name, pname);
+		    } else {
+			addTag(tag, locale);
+		    }
+		}
+	    } else if (name.equals("subhelpset")) {
+		// SUBHELPSET tag
+		
+		// Remove from stack if an empty tag
+		if (tag.isEnd && !tag.isEmpty) {
+		    removeTag(tag);
+		} else {
+		    // Add the tag if it isn't an inline tag
+		    if (!tag.isEmpty) {
+			addTag(tag, locale);
+		    }
+		    // Process the tag
+		    factory.processSubHelpSet(myHS, ht);
+		}
+	    } else if (name.equals("impl")) {
+		// Presentation tag
+		if (tag.isEnd) {
+		    removeTag(tag);
+		    // Nothing to do here. Everything is done while
+		    // processing the sub tags
+		} else {
+		    if (! pname.equals("helpset")) {
+			wrongParent(name, pname);
+		    } else {
+			addTag(tag, locale);
+		    }
+		}
+	    } else if (name.equals("helpsetregistry")) {
+		if (tag.isEnd && !tag.isEmpty) {
+		    removeTag(tag);
+		} else {
+		    if (! pname.equals("impl")) {
+			wrongParent(name, pname);
+		    } else {
+			if (!tag.isEnd) {
+			    addTag(tag, locale);
+			}
+			if (attr != null) {
+			    String hbClass = attr.getProperty("helpbrokerclass");
+			    if (hbClass != null) {
+				myHS.setKeyData(implRegistry,
+						helpBrokerClass, 
+						hbClass);
+			    }
+			}
+		    }
+		}
+	    } else if (name.equals("viewerregistry")) {
+		if (tag.isEnd && !tag.isEmpty) {
+		    removeTag(tag);
+		} else {
+		    if (! pname.equals("impl")) {
+			wrongParent(name, pname);
+		    } else {
+			if (!tag.isEnd) {
+			    addTag(tag, locale);
+			}
+			if (attr != null) {
+			    String viewerType = attr.getProperty("viewertype");
+			    String viewerClass = attr.getProperty("viewerclass");
+			    if (viewerType != null && viewerClass != null) {
+				ClassLoader cl = HelpSet.class.getClassLoader();
+				myHS.setKeyData(kitTypeRegistry,
+						viewerType, viewerClass);
+				myHS.setKeyData(kitLoaderRegistry,
+						viewerType, cl);
+			    }
+			}
+		    }
+		}
+	    }
+	}
+
+	public void piFound(ParserEvent e) {
+	    factory.processPI(myHS, e.getTarget(), e.getData());
+	}
+
+	public void doctypeFound(ParserEvent e) {
+	    factory.processDOCTYPE(e.getRoot(), e.getPublicId(), e.getSystemId());
+	}
+
+	private void checkNull(String name, String t) {
+	    if (! t.equals("")) {
+		parsingError("helpset.wrongText", name, t);
+	    }
+	}
+
+	public void textFound(ParserEvent e) {
+	    debug("textFound: ");
+	    debug("  text: "+e.getText());
+
+	    if (tagStack.empty()) {
+		return;		// ignore
+	    }
+	    LangElement le = (LangElement) tagStack.peek();
+	    Tag tag = le.getTag();
+	    TagProperties attr = tag.atts;
+	    Hashtable ht = (attr == null) ? null : attr.getHashtable();
+	    String text = e.getText().trim();
+	    String name = tag.name;
+
+	    if (name.equals("helpset")) {
+		// HELPSET tag
+		checkNull("helpset", text);
+		return;
+	    }
+	    int depth = tagStack.size();
+	    String pname = "";
+	    if (depth >= 2) {
+		le = (LangElement) tagStack.elementAt(depth-2);
+		pname = ((Tag) le.getTag()).name; // the parent
+	    }
+
+	    if (name.equals("title")) {
+		// TITLE tag
+		if (pname.equals("helpset")) {
+		    factory.processTitle(myHS, text);
+		} else {
+		    presentationTitle = text.trim();
+		}
+	    } else if (name.equals("homeID")) {
+		// HOMEID tag
+		factory.processHomeID(myHS, text);
+	    } else if (name.equals("mapref")) {
+		checkNull("mapref", text);
+	    } else if (name.equals("subhelpset")) {
+		checkNull("subhelpset", text);
+	    } else if (name.equals("data")) {
+		// DATA tag -- this is in a view
+		viewData = text.trim();
+	    } else if (name.equals("label")) {
+		// LABEL tag -- this is in a view
+		viewLabel = text.trim();
+	    } else if (name.equals("name")) {
+		// NAME tag -- this is in a view
+		tagName = text.trim();
+	    } else if (name.equals("helpaction")) {
+		// NAME tag -- this is in a view
+		helpAction = text.trim();
+	    } else if (name.equals("type")) {
+		// TYPE tag -- this is in a view
+		viewType = text.trim();
+            } else if (name.equals("image")) {
+                // IMAGE tag -- this is in the view
+                tagImage = text.trim();
+	    } else if (name.equals("view")) {
+		// VIEW tag
+		checkNull("view", text);
+	    } else if (name.equals("maps")) {
+		// MAP tag
+		checkNull("maps", text);
+            } else if (name.equals("mergetype")) {
+                 checkNull("mergetype",text);
+            }
+	}
+
+	/**
+	 * Method used to parse a HelpSet.
+	 */
+	public void errorFound(ParserEvent e) {
+	    // Ignore it for now
+	}
+
+	/**
+	 * Method used to parse a HelpSet.
+	 */
+	public void commentFound(ParserEvent e) {
+	    // Ignore it for now
+	}
+    
+    	/**
+	 * addTag keeps track of tags and their locale attributes.
+	 */
+	protected void addTag(Tag tag, Locale locale) {
+	    LangElement el = new LangElement(tag, locale);
+	    tagStack.push(el);
+	    // It's possible for lastLocale not be specified ergo null.
+	    // If it is then set lastLocale to null even if locale is null.
+	    // It is impossible for locale to be null
+	    if (lastLocale == null) {
+		lastLocale = locale;
+		return;
+	    }
+	    if (locale == null) {
+		lastLocale = locale;
+		return;
+	    }
+	    if (! lastLocale.equals(locale)) {
+		lastLocale = locale;
+	    }
+	}
+
+	/**
+	 * removeTag removes a tag from the tagStack. The tagStack is
+	 * used to keep track of tags and locales.
+	 */
+	protected void removeTag(Tag tag) {
+	    LangElement el;
+	    String name = tag.name;
+	    Locale newLocale = null;
+
+	    for (;;) {
+		if (tagStack.empty()) 
+		    unbalanced(name);
+		el = (LangElement) tagStack.pop();
+		if (el.getTag().name.equals(name)) {
+		    if (tagStack.empty()) {
+			newLocale = defaultLocale;
+		    } else {
+			el = (LangElement) tagStack.peek();
+			newLocale = el.getLocale();
+		    }
+		    break;
+		}
+	    }
+	    // It's possible for lastLocale not be specified ergo null.
+	    // If it is then set lastLocale to null even if locale is null.
+	    // It also possible for locale to be null so if lastLocale is set
+	    // then reset lastLocale to null;
+	    // Otherwise if lastLocale doesn't equal locale reset lastLocale to locale
+	    if (lastLocale == null) {
+		lastLocale = newLocale;
+		return;
+	    }
+	    if (newLocale == null) {
+		lastLocale = newLocale;
+		return;
+	    }
+	    if (! lastLocale.equals(newLocale)) {
+		lastLocale = newLocale;
+	    }
+	}
+
+	/**
+	 * Handy error message methods.
+	 */
+
+	private void parsingError(String key) {
+	    String s = HelpUtilities.getText(key);
+	    factory.reportMessage(s, false); // tree will be wrong
+	}
+
+	private void parsingError(String key, String s) {
+	    String msg = HelpUtilities.getText(key, s);
+	    factory.reportMessage(msg, false); // tree will be wrong
+	}
+
+	private void parsingError(String key, String s1, String s2) {
+	    String msg = HelpUtilities.getText(key, s1, s2);
+	    factory.reportMessage(msg, false); // tree will be wrong
+	}
+
+	private void wrongParent(String name, String pname) {
+	    parsingError("helpset.wrongParent", name, pname);
+	}
+	
+	private void unbalanced(String name) {
+	    parsingError("helpset.unbalanced", name);
+	}
+
+	private void wrongLocale(Locale found, Locale l1, Locale l2) {
+	    String msg = HelpUtilities.getText("helpset.wrongLocale",
+					     found.toString(),
+					     l1.toString(),
+					     l2.toString());
+	    factory.reportMessage(msg, true); // will continue
+	}
+    } // End of HelpSetParser
+
+    /**
+     * For printf debugging.
+     */
+    private final static boolean debug = false;
+    private static void debug(String str) {
+        if (debug) {
+            System.out.println("HelpSet: " + str);
+        }
+    }
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/HelpSetException.java b/jhMaster/JavaHelp/src/new/javax/help/HelpSetException.java
new file mode 100644
index 0000000000000000000000000000000000000000..21b5baa30c0b68844305c88ae65725164b045cc4
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/HelpSetException.java
@@ -0,0 +1,50 @@
+/*
+ * @(#)HelpSetException.java	1.12 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help;
+
+import java.util.Locale;
+
+/**
+ * This exeception reports generic failures in HelpSet.
+ *
+ * @author Roger D. Brinkley
+ * @author Eduardo Pelegri-Llopart
+ * @version	1.12	10/30/06
+ */
+
+public class HelpSetException extends Exception {
+    /**
+     * Constructs a HelpSetException with a specified detailed message.
+     * A detail message is a String that describes this particular exception.
+     * @params s The detailed message. If s is null it is the same as if
+     * no detailed message was specified.
+     */
+    public HelpSetException(String s) {
+	super(s);
+    }
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/HelpSetFactory.java b/jhMaster/JavaHelp/src/new/javax/help/HelpSetFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..791ff61a835106c097d495ac61dbc53cd185cb10
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/HelpSetFactory.java
@@ -0,0 +1,195 @@
+/*
+ * @(#)HelpSetFactory.java	1.12 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help;
+
+import java.util.Hashtable;
+import java.util.Locale;
+import java.util.Enumeration;
+import java.util.Vector;
+import java.net.URL;
+import java.awt.Dimension;
+import java.awt.Point;
+
+/**
+ * A factory for creating HelpSets.  This can be used to reuse our parser.
+ *
+ * @author Eduardo Pelegri-Llopart
+ * @(#)HelpSetFactory.java 1.12 10/30/06
+ */
+
+interface HelpSetFactory {
+    /**
+     * Parsing starts.
+     *
+     * @param url URL to the document being parsed
+     */
+    public void parsingStarted(URL source);
+
+    /**
+     * Processes a DOCTYPE
+     *
+     * @param root The root tag of the document
+     * @param publicID PublicID from the DOCTYPE
+     * @param systemID SystemID from the DOCTYPE
+     */
+    public void processDOCTYPE(String root, String publicID, String systemID);
+
+    /**
+     * A Processing Instruction.
+     *
+     * @param target The target of the PI
+     * @param data A String for the data in the PI
+     */
+    public void processPI(HelpSet hs,
+			  String target,
+			  String data);
+
+    /**
+     * process <title>
+     *
+     * @param hs The Helpset
+     * @param title The title of the HelpSet
+     */
+    public void processTitle(HelpSet hs,
+			     String title);
+
+    /**
+     * Processes &lt;homeID&gt;.
+     *
+     * @param hs The Helpset
+     * @param homeID The home ID for the helpset
+     */
+    public void processHomeID(HelpSet hs,
+			      String homeID);
+
+    /**
+     * Process a &l;mapref&gt;.
+     *
+     * @param hs The HelpSet
+     * @param Attributes for this tag
+     */
+    public void processMapRef(HelpSet hs,
+			      Hashtable attributes);
+
+    /**
+     * Creates a NavigatorView from the data.
+     *
+     * @param hs The HelpSet
+     */
+
+    public void processView(HelpSet hs,
+			    String name,
+			    String label,
+			    String type,
+			    Hashtable viewAttributes,
+			    String data,
+			    Hashtable dataAttributes,
+			    Locale locale);
+    
+    /**
+     * Processes a sub-HelpSet tag.
+     *
+     * @param base The base URL from where to locate the sub-HelpSet.
+     * @param att A collection of attributes that might be used.
+     * @returns A HelpSet to be added.
+     */
+    public void processSubHelpSet(HelpSet hs,
+				  Hashtable attributes);
+
+    /**
+     * Creates a HelpSet.Presentation from the data. The hs and name
+     * parameters are the only required parameters. All others may be null.
+     *
+     * @param hs The HelpSet
+     * @param name Name of the Presentation
+     * @param default Is the Presenation the default Presentation
+     * @param displayViews Display the Views in the Presentation
+     * @param displayViewImages Display the Views Images in the Presentation
+     * @param size Size of the Presentation
+     * @param location Location of the Presentation
+     * @param title Title for the presentation
+     * @param toolbar Is there a custom toolbar for the presentation
+     * @param helpActions A Vector of HelpAction(s).
+     * 
+     * 
+     */
+
+    public void processPresentation(HelpSet hs,
+				    String name,
+				    boolean defaultPresentation,
+				    boolean displayViews,
+				    boolean displayViewImages,
+				    Dimension size,
+				    Point location,
+				    String title,
+				    String imageMapID,
+				    boolean toolbar,
+				    Vector helpActions);
+    
+    /**
+     * Reports some parsing error.
+     *
+     * @param msg The message to report.
+     * @param validParse Whether the on-going parse should return a valid object.
+     */
+    public void reportMessage(String msg, boolean validParse);
+
+    /**
+     * Enumerated all the error mesages.
+     */
+    public Enumeration listMessages();
+
+    /**
+     * Parsing ends.  Last chance to do something
+     * to the HelpSet
+     */
+    public HelpSet parsingEnded(HelpSet hs);
+
+    /**
+     * Internal storage of HelpAction defined in a Presentaion
+     */
+    public class HelpAction {
+
+	/**
+	 * Name of the Action
+	 */
+	public String className = null;
+
+	/**
+	 * Attributes of the Action
+	 */
+	public Hashtable attr = null;
+
+	public HelpAction (String className, Hashtable attr) {
+	    this.className = className;
+	    this.attr = attr;
+	}
+    }
+
+
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/HelpUtilities.java b/jhMaster/JavaHelp/src/new/javax/help/HelpUtilities.java
new file mode 100644
index 0000000000000000000000000000000000000000..8c6b76b3533cadd725afc9d64fbd89c606618e77
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/HelpUtilities.java
@@ -0,0 +1,881 @@
+/*
+ * @(#)HelpUtilities.java	1.56 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help;
+
+import java.net.URL;
+
+import java.io.InputStream;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Locale;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+import java.util.Vector;
+
+import java.beans.BeanInfo;
+import java.beans.Introspector;
+
+import java.text.CollationElementIterator;
+import java.text.Collator;
+import java.text.MessageFormat;
+import java.text.RuleBasedCollator;
+
+import java.awt.Component;
+import java.awt.IllegalComponentStateException;
+
+
+/**
+ * Provides a number of utility functions:
+ *
+ * Support for Beans, mapping from a Bean class to its HelpSet and to
+ * its ID.
+ * Support for finding localized resources.
+ * Support for getting the default Query Engine
+ *
+ * This class has no public constructor.
+ *
+ * @author Eduardo Pelegri-Llopart
+ * @author Roger D. Brinkley
+ * @version	1.56	10/30/06
+ */
+
+public class HelpUtilities {
+
+    //=========
+
+    /**
+     * Beans support
+     */
+
+    /**
+     * Given the class for a bean, get its HelpSet.
+     * Returns the helpSetName property of the BeanDescriptor if defined.
+     * Otherwise it returns a name as follows:
+     * If the class is in the unnamed package, it returns <em>beanClassName</em>Help.hs.
+     * Otherwise if it's in the form <em>package.ClassName</em> it returns
+     * <em>package</em>/Help.hs after replacing "." with "/" in <em>package</em>.
+     *
+     * @param beanClass The Class
+     * @return A String with the name of the HelpSet
+     */
+
+    public static String getHelpSetNameFromBean(Class beanClass) {
+	String helpSetName;
+	try {
+	    BeanInfo bi = Introspector.getBeanInfo(beanClass);
+	    helpSetName =
+		(String) bi.getBeanDescriptor().getValue("helpSetName");
+	} catch (Exception ex) {
+	    helpSetName = null;
+	}
+	if (helpSetName == null) {
+	    String className = beanClass.getName();
+	    int index = className.lastIndexOf(".");
+	    if (index == -1) {
+		// unnamed package
+		helpSetName = className + "Help.hs";
+	    } else {
+		String packageName = className.substring(0, index);
+		helpSetName = packageName.replace('.','/') + "/Help.hs";
+	    }
+	}
+	return helpSetName;
+    }
+
+    /**
+     * Given the class for a bean, get its ID string.
+     * Returns the helpID property of the BeanDescriptor if defined,
+     * otherwise it returns <em>beanName</em>.topID.
+     *
+     * @param beanClass the Class
+     * @return A String with the ID to use
+     */
+
+    public static String getIDStringFromBean(Class beanClass) {
+	String helpID;
+	try {
+	    BeanInfo bi = Introspector.getBeanInfo(beanClass);
+	    helpID = (String) bi.getBeanDescriptor().getValue("helpID");
+	} catch (Exception ex) {
+	    helpID = null;
+	}
+	if (helpID == null) {
+	    String className = beanClass.getName();
+	    helpID = className + ".topID";
+	}
+	return helpID;
+    }
+
+
+    //=======
+    /**
+     * Default for the search engine
+     */
+    public static String getDefaultQueryEngine() {
+	return "com.sun.java.help.search.DefaultSearchEngine";
+    }
+
+    //========
+
+    /**
+     * I18N/ L10N support
+     */
+
+    /**
+     * Search for a helpset file following the standard conventions
+     * used in ResourceBundle.
+     */
+
+    /**
+     * Locate a resource relative to a given classloader CL.
+     * The name of the resource is composed by using FRONT,
+     * adding _LANG _COUNTRY _VARIANT (with the usual rules)
+     * and ending with BACK, which will usually be an extension
+     * like ".hs" for a HelpSet, or ".class" for a class
+     *
+     * This method is a convenience method for getLocalizedResource() with
+     * a tryRead parameter set to false.
+     *
+     * This functionality should likely be exposed as part of JDK1.2
+     * @param cl The ClassLoader to get the resource from. If cl is null the default 
+     * ClassLoader is used.
+     * @returns the URL to the localized resource or null if not found.
+     */
+    public static URL getLocalizedResource(ClassLoader cl,
+					   String front,
+					   String back,
+					   Locale locale) {
+	return getLocalizedResource(cl, front, back, locale, false);
+    }
+
+    /**
+     * Locate a resource relative to a given classloader CL.
+     * The name of the resource is composed by using FRONT,
+     * adding _LANG _COUNTRY _VARIANT (with the usual rules)
+     * and ending with BACK, which is usually an extension
+     * like ".hs" for a HelpSet, or ".class" for a class
+     *
+     * This version accepts an explicit argument to work around some browser bugs.
+     * 
+     * This functionality should likely be exposed as part of JDK1.2
+     * @param cl The ClassLoader to get the resource from. If cl is null the default
+     * ClassLoader is used.
+     * @returns the URL to the localized resource or null if not found.
+     */
+    public static URL getLocalizedResource(ClassLoader cl,
+					   String front,
+					   String back,
+					   Locale locale,
+					   boolean tryRead) {
+	URL url;
+	for (Enumeration tails = getCandidates(locale);
+	     tails.hasMoreElements(); ) {
+	    String tail = (String) tails.nextElement();
+	    String name	= (new StringBuffer(front)).append(tail).append(back).toString();
+	    if (cl == null) {
+		url = ClassLoader.getSystemResource(name);
+	    } else {
+		url = cl.getResource(name);
+	    }
+	    if (url != null) {
+		if (tryRead) {
+		    // Try doing an actual read to be sure it exists
+		    try {
+			InputStream is = url.openConnection().getInputStream();
+			if (is != null) {
+			    int i = is.read();
+			    is.close();
+			    if (i != -1) {
+				return url;
+			    }
+			}
+		    } catch (Throwable t) {
+		        // ignore and continue looking
+		    }
+		} else {
+		    return url;
+		}
+	    }
+	}
+	return null;
+    }
+
+    private static Hashtable tailsPerLocales = new Hashtable();
+
+    /**
+     * This returns an enumeration of String tails. 
+     * 
+     * The core functionality on which getLocalizedResource is based.
+     *
+     * The suffixes are based on (1) the desired locale and (2) the default locale
+     * in the following order from lower-level (more specific) to parent-level
+     * (less specific):
+     * <p>  "_" + language1 + "_" + country1 + "_" + variant1
+     * <BR> "_" + language1 + "_" + country1
+     * <BR> "_" + language1
+     * <BR> ""
+     * <BR> "_" + language2 + "_" + country2 + "_" + variant2
+     * <BR> "_" + language2 + "_" + country2
+     * <BR> "_" + language2
+     *
+     * The enumeration is of StringBuffer.
+     * We pay some attention to efficiency in case a method like this is promoted,
+     * hence we cache per locale.
+     */
+
+    public static synchronized Enumeration getCandidates(Locale locale) {
+	Vector tails;
+	LocalePair pair = new LocalePair(locale, Locale.getDefault());
+	tails = (Vector) tailsPerLocales.get(pair);
+	if (tails != null) {
+	    debug("getCandidates - cached copy");
+	    return tails.elements();
+	}
+
+	String lname1 = locale.toString();
+	StringBuffer name1 = new StringBuffer("_").append(lname1);
+	if (lname1 == null) {
+	    name1.setLength(0);
+	}
+	tails = new Vector();
+	// Now add them to the vector
+	while (name1.length() != 0) {
+	    debug("  adding ", name1);
+	    String s = name1.toString();
+	    tails.addElement(s);
+	    int lastUnder = s.lastIndexOf('_');
+	    if (lastUnder != -1) {
+		name1.setLength(lastUnder);
+	    }
+	}
+	debug("  addign -- null -- ");
+	tails.addElement("");
+	if (locale != Locale.getDefault()) {
+	    // Otherwise, no need to search twice
+	    String lname2 = Locale.getDefault().toString();
+	    StringBuffer name2 = new StringBuffer("_").append(lname2);
+	    if (lname2 == null) {
+		name2.setLength(0);
+	    }
+	    while (name2.length() != 0) {
+		debug("  adding ", name2);
+		String s = name2.toString();
+		tails.addElement(s);
+		int lastUnder = s.lastIndexOf('_');
+		if (lastUnder != -1) {
+		    name2.setLength(lastUnder);
+		}
+	    }
+	}
+	tailsPerLocales.put(pair, tails);
+	debug("tails is == ", tails);
+	return tails.elements();
+    }
+
+    /**
+     * Auxiliary class used in dealing with locale.
+     */
+    
+    static class LocalePair {
+	LocalePair(Locale locale1, Locale locale2) {
+	    this.locale1 = locale1;
+	    this.locale2 = locale2;
+	}
+	
+	public int hashCode() {
+	    return locale1.hashCode() + locale2.hashCode();
+	}
+	
+	public boolean equals(Object obj) {
+	    if (obj == null || ! (obj instanceof LocalePair)) {
+		return false;
+	    } else {
+		LocalePair p = (LocalePair) obj;
+		return locale1.equals(p.locale1) && locale2.equals(p.locale2);
+	    }
+	}
+	
+	Locale locale1;
+	Locale locale2;
+    }
+
+    // ==========
+
+    /**
+     * Get a localized Error String
+     */
+    private static Hashtable bundles;
+    private static ResourceBundle lastBundle = null;
+    private static Locale lastLocale = null;
+
+    /**
+     * Gets the locale of a component. If the component is null
+     * it returns the defaultLocale. If the call to component.getLocale
+     * returns an IllegalComponentStateException, the defaultLocale is
+     * returned.
+     */
+    public static Locale getLocale(Component c) {
+	if (c == null) {
+	    return Locale.getDefault();
+	}
+	try {
+	    return c.getLocale();
+	} catch (IllegalComponentStateException ex) {
+	    return Locale.getDefault();
+	}
+	      
+    }
+
+    static synchronized private ResourceBundle getBundle(Locale l) {
+	if (lastLocale == l) {
+	    return lastBundle;
+	}
+	if (bundles == null) {
+	    bundles = new Hashtable();
+	}
+	ResourceBundle back = (ResourceBundle) bundles.get(l);
+	if (back == null) {
+	    try {
+		back = ResourceBundle.getBundle("javax.help.resources.Constants",
+						l);
+	    } catch (MissingResourceException ex) {
+		throw new Error("Fatal: Resource for javahelp is missing");
+	    }
+	    bundles.put(l, back);
+	}
+	lastBundle = back;
+	lastLocale = l;
+	return back;
+    }
+
+
+    /**
+     * Get the Text message for the default locale.
+     *
+     * The getString version does not involve a format.
+     */
+    static public String getString(String key) {
+	return getString(Locale.getDefault(), key);
+    }
+
+    static public String getText(String key) {
+	return getText(Locale.getDefault(), key, null, null);
+    }
+
+    /**
+     * @param s1 The first parameter of a string. A null is valid for s1.
+     */
+    static public String getText(String key, String s1) {
+	return getText(Locale.getDefault(), key, s1, null);
+    }
+
+    /**
+     * @param s1 The first parameter of a string. A null is valid for s1.
+     * @param s2 The first parameter of a string. A null is valid for s2.
+     */
+    static public String getText(String key, String s1, String s2) {
+	return getText(Locale.getDefault(), key, s1, s2);
+    }
+
+    /**
+     * @param s1 The first parameter of a string. A null is valid for s1.
+     * @param s2 The first parameter of a string. A null is valid for s2.
+     * @param s3 The first parameter of a string. A null is valid for s3.
+     */
+    static public String getText(String key, String s1, String s2, String s3) {
+	return getText(Locale.getDefault(), key, s1, s2, s3);
+    }
+
+    /**
+     * Versions with an explicit locale.
+*/
+    static public String getString(Locale l, String key) {
+	ResourceBundle bundle = getBundle(l);
+	try {
+	    return bundle.getString(key);
+	} catch (MissingResourceException ex) {
+	    throw new Error("Fatal: Localization data for JavaHelp is broken.  Missing "+key+" key.");
+	}
+    }
+
+    static public String[] getStringArray(Locale l, String key) {
+	ResourceBundle bundle = getBundle(l);
+	try {
+	    return bundle.getStringArray(key);
+	} catch (MissingResourceException ex) {
+	    throw new Error("Fatal: Localization data for JavaHelp is broken.  Missing "+key+" key.");
+	}
+    }
+
+    /**
+     * @param s1 The first parameter of a string. A null is valid for s1.
+     * @param s2 The first parameter of a string. A null is valid for s2.
+     * @param s3 The first parameter of a string. A null is valid for s3.
+     */
+    static public String getText(Locale l, String key) {
+	return getText(l, key, null, null, null);
+    }
+
+    /**
+     * @param s1 The first parameter of a string. A null is valid for s1.
+     */
+    static public String getText(Locale l, String key, String s1) {
+	return getText(l, key, s1, null, null);
+    }
+
+    /**
+     * @param s1 The first parameter of a string. A null is valid for s1.
+     * @param s2 The first parameter of a string. A null is valid for s2.
+     */
+    static public String getText(Locale l, String key, String s1, String s2) {
+	return getText(l, key, s1, s2, null);
+    }
+
+    /**
+     * @param s1 The first parameter of a string. A null is valid for s1.
+     * @param s2 The first parameter of a string. A null is valid for s2.
+     * @param s3 The first parameter of a string. A null is valid for s3.
+     */
+    static public String getText(Locale l, String key,
+				 String s1, String s2, String s3) {
+	ResourceBundle bundle = getBundle(l);
+	// workaround bugs in JDK 1.1.6
+	// This mimic's what JDK 1.2 will do.
+	if (s1 == null) {
+	    s1 = "null";
+	}
+	if (s2 == null) {
+	    s2 = "null";
+	}
+	if (s3 == null) {
+	    s3 = "null";
+	}
+	// end workaround
+	try {
+	    String fmt = bundle.getString(key);
+	    String[] args = {s1, s2, s3};
+	    MessageFormat format = new MessageFormat(fmt);
+	    // workaround a bug in MessageFormat.setLocale
+	    try {
+		format.setLocale(l);
+	    } catch (NullPointerException ee) {
+	    }
+	    return format.format(args);
+	} catch (MissingResourceException ex) {
+	    throw new Error("Fatal: Localization data for JavaHelp is broken.  Missing "+key+" key.");
+	}
+    }
+
+    /**
+     * Convenient method for creating a locale from a <tt>lang</tt> string.
+     * Takes the <tt>lang</tt> string in the form of "language_country_variant"
+     * or "language-country-variant" and 
+     * parses the string and creates an appropriate locale.
+     * @param lang A String representation of a locale, with the language, 
+     * country and variant separated by underbars. Language is always lower
+     * case, and country is always upper case. If the language is missing the
+     * String begins with an underbar. If both language and country fields are
+     * missing, a null Locale is returned. If lang is null a null Locale is 
+     * returned
+     * @returns The locale based on the string or null if the Locale could
+     * not be constructed or lang was null.
+     */
+    public static Locale localeFromLang(String lang) {
+	String language;
+	String country;
+	String variant=null;
+	Locale newlocale=null;
+	if (lang == null) {
+	    return newlocale;
+	}
+	int lpt = lang.indexOf("_");
+	int lpt2 = lang.indexOf("-");
+	if (lpt == -1 && lpt2 == -1) {
+	    language = lang;
+	    country = "";
+	    newlocale = new Locale(language, country);
+	} else {
+	    if (lpt == -1 && lpt2 != -1) {
+		lpt = lpt2;
+	    }
+	    language = lang.substring(0, lpt);
+	    int cpt = lang.indexOf("_", lpt+1);
+	    int cpt2 = lang.indexOf("-", lpt+1);
+	    if (cpt == -1 && cpt2 == -1) {
+		country = lang.substring(lpt+1);
+		newlocale = new Locale(language, country);
+	    } else {
+		if (cpt == -1 && cpt2 != -1) {
+		    cpt = cpt2;
+		}
+		country = lang.substring(lpt+1, cpt);
+		variant = lang.substring(cpt+1);
+		newlocale = new Locale(language, country, variant);
+	    }
+	}
+	return newlocale;
+    }
+
+    /**
+     * Returns information about whether a string is 
+     * contained in another string. Compares the character data stored in two 
+     * different strings based on the collation rules. 
+     */
+    public static boolean isStringInString(RuleBasedCollator rbc, 
+					   String source,
+					   String target) {
+        // The basic algorithm here is that we use CollationElementIterators
+        // to step through both the source and target strings.  We compare each
+        // collation element in the source string against the corresponding one
+        // in the target, checking for differences.
+        //
+        // If a difference is found, we set <result> to false.
+        //
+        // However, it's not that simple.  If we find a tertiary difference
+        // (e.g. 'A' vs. 'a') near the beginning of a string, it can be
+        // overridden by a primary difference (e.g. "A" vs. "B") later in
+        // the string.  For example, "AA" < "aB", even though 'A' > 'a'.
+        //
+        // To keep track of this, we use strengthResult to keep track of the
+        // strength of the most significant difference that has been found
+        // so far.  When we find a difference whose strength is greater than
+        // strengthResult, it overrides the last difference (if any) that
+        // was found.
+
+	debug("isStringInString source=" + source + " targe =" + target); 
+	    
+	// Initial sanity checks
+	if (source == null || target == null) {
+	    return false;
+	}
+	if (source.length() == 0 && target.length() == 0) {
+	    return true;
+	}
+
+	// on to the real code
+        int strengthResult = Collator.IDENTICAL;
+        CollationElementIterator sourceCursor, targetCursor;
+	boolean isFrenchSec = false;
+
+	// set up the RuleBasedCollator and extract
+	// various attributes
+	rbc.setDecomposition(Collator.FULL_DECOMPOSITION);
+	String rules = rbc.getRules();
+	if (rules.startsWith("@")) {
+	    // I suspect we are cheating here when multiple rules are merged
+	    // One would think you could get this attribute but you can't
+	    isFrenchSec = true;
+	}
+
+	// Get the CollationElementIterators for the source and target
+	sourceCursor = rbc.getCollationElementIterator(source);
+	targetCursor = rbc.getCollationElementIterator(target);
+        
+	// Various locale specific matching parameters
+        int sOrder = 0, tOrder = 0;
+	int pSOrder, pTOrder;
+	short secSOrder, secTOrder;
+	short terSOrder, terTOrder;
+        boolean gets = true, gett = true;
+	int toffset = 0;
+        boolean initialCheckSecTer, checkSecTer, checkTertiary;
+
+   startSearchForFirstMatch:
+        while(true) {
+	    debug("while(true) toffset=" + toffset);
+	    // Set the starting point for this comparison
+	    try {
+		sourceCursor.setOffset(0);
+	    } catch (NoSuchMethodError ex3) {
+		// ingnore it
+	    }
+	    sOrder = sourceCursor.next();
+	    try {
+		targetCursor.setOffset(toffset);
+	    } catch (NoSuchMethodError ex4) {
+		// Can't really do anything here. Return false.
+	    } catch (Exception e) {
+		// We can get an exception when the toffset is really the
+		// end of string
+		// Just catch it and return false;
+		return false;
+	    }
+	    tOrder = targetCursor.next();
+
+	    if (tOrder == CollationElementIterator.NULLORDER) {
+		break;
+	    }
+
+	    debug("sOrder=" + sOrder + " tOrder=" + tOrder);
+
+	    //Find the first character in the target that matches the first
+	    // character in the source. Look for a complete match of
+	    // primary, secondary and tertiary. Lacking that look for
+	    // a match of just primary.
+	    while (tOrder != CollationElementIterator.NULLORDER) {
+		if (sOrder == tOrder) {
+		    try {
+			toffset = targetCursor.getOffset();
+		    } catch (NoSuchMethodError ex) {
+			//ignore it
+		    }
+		    break;
+		}
+		pSOrder = CollationElementIterator.primaryOrder(sOrder);
+		pTOrder = CollationElementIterator.primaryOrder(tOrder);
+		if (pSOrder == pTOrder) {
+		    try {
+			toffset = targetCursor.getOffset();
+		    } catch (NoSuchMethodError ex2) {
+			//ignore it
+		    }
+		    break;
+		}
+		tOrder = targetCursor.next();
+		debug("next tOrder=" + tOrder);
+	    }
+
+	    // If at end there is no match
+	    if (tOrder == CollationElementIterator.NULLORDER) {
+		return false;
+	    }
+
+	    gets = false;
+	    gett = false;
+	    initialCheckSecTer = rbc.getStrength() >= Collator.SECONDARY;
+	    checkSecTer = initialCheckSecTer;
+	    checkTertiary = rbc.getStrength() >= Collator.TERTIARY;
+	    
+	    while (true) {
+		// Get the next collation element in each of the strings, unless
+		// we've been requested to skip it.
+		if (gets) {
+		    sOrder = sourceCursor.next(); 
+		} else {
+		    gets = true;
+		}
+		if (gett) {
+		    tOrder = targetCursor.next(); 
+		} else {
+		    gett = true;
+		}
+
+		// If we've hit the end of one of the strings, jump out of the loop
+		if ((sOrder == CollationElementIterator.NULLORDER)||
+		    (tOrder == CollationElementIterator.NULLORDER)) {
+		    debug("One string at end");
+		    break;
+		}
+
+		pSOrder = CollationElementIterator.primaryOrder(sOrder);
+		pTOrder = CollationElementIterator.primaryOrder(tOrder);
+
+            // If there's no difference at this position, we can skip it
+		if (sOrder == tOrder) {
+		    if (isFrenchSec && pSOrder != 0) {
+			if (!checkSecTer) {
+			    // in french, a secondary difference more to the
+			    // right is stronger,
+			    // so accents have to be checked with each base
+			    // element
+			    checkSecTer = initialCheckSecTer;
+			    // but tertiary differences are less important
+			    // than the first 
+			    // secondary difference, so checking tertiary
+			    // remains disabled
+			    checkTertiary = false;
+			}
+		    }
+		    debug("No diff at this positon continue");
+		    continue;
+		}
+
+		// Compare primary differences first.
+		if ( pSOrder != pTOrder ) {
+		    if (sOrder == 0) {
+			// The entire source element is ignorable.
+			// Skip to the next source element, 
+			// but don't fetch another target element.
+			gett = false;
+			continue;
+		    }
+		    if (tOrder == 0) {
+			// The entire target element is ignorable.
+			// Skip to the next target element, 
+			// but don't fetch another source element.
+			gets = false;
+			continue;
+		    }
+
+		    // The source and target elements aren't ignorable,
+		    // but it's still possible
+		    // for the primary component of one of the elements
+		    // to be ignorable....
+		    
+		    if (pSOrder == 0) {
+			// The source's primary is ignorable, 
+			// but the target's isn't.  We treat ignorables
+			// as a secondary differenc
+			if (checkSecTer) {
+			    // (strength is SECONDARY)
+			    targetCursor.next();
+			    toffset = targetCursor.getOffset();
+			    debug("Strength is secondary pSOrder === 0");
+			    continue startSearchForFirstMatch;
+			}
+			// Skip to the next source element, 
+			// but don't fetch another target element.
+			gett = false;
+		    } else if (pTOrder == 0) {
+			// record differences - see the comment above.
+			if (checkSecTer) {
+			    // (stength is SECONDARY)
+			    targetCursor.next();
+			    toffset = targetCursor.getOffset();
+			    debug("Strength is secondary - pTOrder == 0");
+			    continue startSearchForFirstMatch;
+			}
+			// Skip to the next source element, 
+			// but don't fetch another target element.
+			gets = false;
+		    } else {
+			// Neither of the orders is ignorable,
+			// and we already know that the primary
+			// orders are different because of the 
+			// (pSOrder != pTOrder) test above.
+			// Record the difference and stop the
+			// comparison.
+			targetCursor.next();
+			toffset = targetCursor.getOffset();
+			debug("Order are ignorable");
+			continue startSearchForFirstMatch;
+		    }
+		} else { // else of if ( pSOrder != pTOrder )
+		    // primary order is the same, but complete order is 
+		    // different. So there
+		    // are no base elements at this point, only 
+		    // ignorables (Since the strings are
+		    // normalized)
+		    
+		    if (checkSecTer) {
+			// a secondary or tertiary difference may 
+			// still matter
+			secSOrder = CollationElementIterator.secondaryOrder(sOrder);
+			secTOrder = CollationElementIterator.secondaryOrder(tOrder);
+			if (secSOrder != secTOrder) {
+			    // there is a secondary difference
+			    targetCursor.next();
+			    toffset = targetCursor.getOffset();
+			    debug("Secondary Difference");
+			    continue startSearchForFirstMatch;
+			    // (strength is SECONDARY)
+			    // (even in french, only the first 
+			    // secondary difference within
+			    // a base character matters)
+			} else {
+			    if (checkTertiary) {
+				// a tertiary difference may still matter
+				terSOrder = CollationElementIterator.tertiaryOrder(sOrder);
+				terTOrder = CollationElementIterator.tertiaryOrder(tOrder);
+				if (terSOrder != terTOrder) {
+				    // there is a tertiary difference
+				    targetCursor.next();
+				    toffset = targetCursor.getOffset();
+				    debug("Tertiary difference");
+				    continue startSearchForFirstMatch;
+				    // (strength is TERTIARY)
+				}
+			    }
+			}
+		    } // if (checkSecTer)
+
+		}  // if ( pSOrder != pTOrder )
+	    } // while()
+
+	    // There might be a match
+	    // Just do some final checking
+	    if (sOrder != CollationElementIterator.NULLORDER) {
+		// (tOrder must be CollationElementIterator::NULLORDER,
+		// since this point is only reached when sOrder or 
+		// tOrder is NULLORDER.)
+		// The source string has more elements, 
+		// but the target string hasn't.
+		do {
+		    if (CollationElementIterator.primaryOrder(sOrder) != 0) {
+			// We found an additional non-ignorable base 
+			// character in the source string.
+			// This is a primary difference, 
+			// so the source is greater
+			targetCursor.next();
+			toffset = targetCursor.getOffset();
+			debug("Additional non-ignborable base character in source string - source is greater");
+			continue startSearchForFirstMatch;
+			// (strength is PRIMARY)
+		    }
+		    else if (CollationElementIterator.secondaryOrder(sOrder) != 0) {
+			// Additional secondary elements mean the 
+			// source string is greater
+			if (checkSecTer) {
+			    targetCursor.next();
+			    toffset = targetCursor.getOffset();
+			    debug("Additional secondary elements source is greater");
+			    continue startSearchForFirstMatch;
+			    // (strength is SECONDARY)
+			}
+		    } 
+		} while ((sOrder = sourceCursor.next()) != CollationElementIterator.NULLORDER);
+	    }
+	    // Either the target string has more elements, 
+	    // but the source string hasn't or neither the target string
+	    // or the source string have any more elemnts.
+	    // In either case the source was contained in target
+	    // return true;
+	    return true;
+	}
+	return false;
+    }
+
+
+
+    /**
+     * Debug support
+     */
+
+    private static final boolean debug = false;
+    private static void debug(Object msg1, Object msg2, Object msg3) {
+	if (debug) {
+	    System.err.println("HelpUtilities: "+msg1+msg2+msg3);
+	}
+    }
+    private static void debug(Object msg1) { debug(msg1,"",""); }
+    private static void debug(Object msg1, Object msg2) {
+	debug(msg1,msg2,"");
+    }
+
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/HomeAction.java b/jhMaster/JavaHelp/src/new/javax/help/HomeAction.java
new file mode 100644
index 0000000000000000000000000000000000000000..0ecfafda19a6bd88e710fa15997dcb292551c436
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/HomeAction.java
@@ -0,0 +1,78 @@
+/*
+ * @(#)HomeAction.java	1.4 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.help.*;
+import javax.help.event.*;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.Stack;
+import javax.swing.*;
+
+/**
+ *
+ * @author Stepan Marek
+ * @version	1.4	10/30/06
+ */
+public class HomeAction extends AbstractHelpAction implements ActionListener {
+    
+    private static final String NAME = "HomeAction";
+    
+    /** Creates new HomeAction */
+    public HomeAction(Object control) {
+        super(control, NAME);
+        
+        putValue("icon", UIManager.getIcon(NAME + ".icon"));
+        
+        if (control instanceof JHelp) {
+	    JHelp help = (JHelp) control;
+	    Locale locale = null;
+	    try {
+		locale = help.getModel().getHelpSet().getLocale();
+	    } catch (NullPointerException npe) {
+		locale = Locale.getDefault();
+	    }
+            putValue("tooltip", HelpUtilities.getString(locale, "tooltip." + NAME));
+            putValue("access", HelpUtilities.getString(locale, "access." + NAME));
+        }
+    }
+    
+    public void actionPerformed(java.awt.event.ActionEvent event) {
+        try {
+            JHelp help = (JHelp)getControl();
+            HelpSet hs = help.getModel().getHelpSet();
+            Map.ID homeID = hs.getHomeID();
+            Locale locale = hs.getLocale();
+            String string = HelpUtilities.getString(locale, "history.homePage");
+            help.setCurrentID(homeID, string, help.getCurrentNavigator());
+        } catch (Exception e) {
+        }
+    }
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/IndexItem.java b/jhMaster/JavaHelp/src/new/javax/help/IndexItem.java
new file mode 100644
index 0000000000000000000000000000000000000000..91e4f8356d694267eb9eca6387078b5cd788eea5
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/IndexItem.java
@@ -0,0 +1,76 @@
+/*
+ * @(#)IndexItem.java	1.18 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help;
+
+import java.util.Vector;
+import java.util.Locale;
+import javax.help.Map.ID;
+
+/**
+ * A class for individual index items.
+ *
+ * @author Roger D. Brinkley
+ * @author Eduardo Pelegri-Llopart
+ * @version	1.18	10/30/06
+ */
+
+public class IndexItem extends TreeItem {
+
+    /**
+     * Create an IndexItem.
+     *
+     * @param id ID for the item. The ID can be null.
+     * @param hs A HelpSet scoping this item.
+     * @param locale The locale for this item
+     */
+    public IndexItem(ID id, HelpSet hs, Locale locale) {
+	super(id, hs, locale);
+    }
+
+    /**
+     * Create an IndexItem defaulting the HelpSet to that of its ID.
+     *
+     * @param id ID for the item. The ID can be null.
+     * @param locale The locale to use for this item.
+     */
+    public IndexItem(ID id, Locale locale) {
+	super(id, locale);
+	HelpSet hs = null;
+	if (id != null) {
+	    setHelpSet(id.hs);
+	}
+
+    }
+
+    /**
+     * Create a default IndexItem.
+     */
+    public IndexItem() {
+	super(null, null, null);
+    }
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/IndexView.java b/jhMaster/JavaHelp/src/new/javax/help/IndexView.java
new file mode 100644
index 0000000000000000000000000000000000000000..c423efad26114a6063a43494461522f972f4a212
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/IndexView.java
@@ -0,0 +1,620 @@
+/*
+ * @(#)IndexView.java	1.32 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help;
+
+import java.awt.Component;
+import java.net.URL;
+import java.net.URLConnection;
+import java.io.Reader;
+import java.io.IOException;
+import java.util.Stack;
+import java.util.Hashtable;
+import java.util.Locale;
+import java.util.Vector;
+import java.util.Enumeration;
+import javax.help.Map.ID;
+import javax.swing.tree.TreeNode;
+import javax.swing.tree.DefaultMutableTreeNode;
+
+import com.sun.java.help.impl.*;
+
+
+/**
+ * Navigational View information for an Index
+ *
+ * @author Eduardo Pelegri-Llopart
+ * @version	1.17	03/16/99
+ */
+
+public class IndexView extends NavigatorView {
+
+    /**
+     * PublicID (known to this XML processor) to the DTD for version 1.0 of the Index
+     */
+    public static final String publicIDString =
+        "-//Sun Microsystems Inc.//DTD JavaHelp Index Version 1.0//EN";
+
+    /**
+     * PublicID (known to this XML processor) to the DTD for version 2.0 of the Index
+     */
+    public static final String publicIDString_V2 =
+        "-//Sun Microsystems Inc.//DTD JavaHelp Index Version 2.0//EN";
+
+    /**
+     * Construct an IndexView with some given data.  Locale defaults to that
+     * of the HelpSet.
+     *
+     * @param hs The HelpSet that provides context information
+     * @param name The name of the View
+     * @param label The label (to show the user) of the View
+     * @param params A hashtable providing different key/values for this type.
+     * A null for params is valid.
+     */
+    public IndexView(HelpSet hs,
+		     String name,
+		     String label,
+		     Hashtable params) {
+	super(hs, name, label, hs.getLocale(), params);
+    }
+
+    /**
+     * Constructs an IndexView with some given data. 
+     *
+     * @param hs The HelpSet that provides context information
+     * @param name The name of the View
+     * @param label The label (to show the user) of the View
+     * @param locale The default locale to interpret the data in this TOC. A
+     * null for locale will be interpreted as the defaultLocale.
+     * @param params A Hashtable providing different key/values for this type
+     * A null for params is valid.
+     */
+    public IndexView(HelpSet hs,
+		     String name,
+		     String label,
+		     Locale locale,
+		     Hashtable params) {
+	super(hs, name, label, locale, params);
+    }
+
+    /**
+     * create a navigator for a given model.
+     * @param model The HelpModel to create this navigator with. A null model
+     * is valid.
+     * @return The appropriate Component for this view.
+     */
+    public Component createNavigator(HelpModel model) {
+	return new JHelpIndexNavigator(this, model);
+    }
+
+    
+    /**
+     * Get the Index navigators mergeType. Overrides getMergeType in NavigatorView
+     */
+    public String getMergeType() {
+	String mergeType = super.getMergeType();
+	if (mergeType == null) {
+	    return "javax.help.AppendMerge";
+	}
+	return mergeType;
+    }
+
+    // turn this on if you want messages on failures
+    private static boolean warningOfFailures = false;
+
+    /**
+     * Gets a DefaultMutableTreeNode representing the 
+     * information in this view instance.
+     * 
+     * The default implementation parses the data in the URL, but a subclass may
+     * override this method and provide a different implemenation. For example,
+     * it may create the tree programatically.
+     */
+    public DefaultMutableTreeNode getDataAsTree() {
+	HelpSet hs = getHelpSet();
+        debug("helpSet in "+this+hs.toString());
+	Hashtable params = getParameters();
+	URL url;
+
+	if (params == null || 
+	    (params != null && !params.containsKey("data"))) {
+	    DefaultMutableTreeNode node = new DefaultMutableTreeNode();
+	    return node;
+	}
+
+	try {
+	    url = new URL(hs.getHelpSetURL(), (String) params.get("data"));
+	} catch (Exception ex) {
+	    throw new Error("Trouble getting URL to Index data; "+ex);
+	}
+        debug("url,hs: "+url.toString()+";"+hs.toString());
+	return parse(url, hs, hs.getLocale(), new DefaultIndexFactory());
+    }
+
+    /**
+     * Public method for parsing an Index in a URL.
+     * It returns a DefaultMutableTreeNode and its children
+     * that correspond to the indexitems in the Index.  The factory is invoked to create
+     * the TreeItems that are included in the DefaultMutableTreeNode as user
+     * data.
+     *
+     * @param url Location of the Index. If null, causes null value to be returned.
+     * @param hs The HelpSet context for this Index. Null hs is ignored.
+     * @param locale The default locale to interpret the data in this Index. Null
+     * locale is treated as the default locale.
+     * @param factory A factory instance that is used to create the IndexItems
+     * @return a TreeNode that represents the Index. Returns null if parsing errors 
+     * were encountered.
+     */
+    public static DefaultMutableTreeNode parse(URL url,
+					HelpSet hs,
+					Locale locale,
+					TreeItemFactory factory) {
+	Reader src;
+	DefaultMutableTreeNode node = null;
+	try {
+	    URLConnection uc = url.openConnection();
+	    src = XmlReader.createReader(uc);
+	    factory.parsingStarted(url);
+	    node = (new IndexParser(factory)).parse(src, hs, locale);
+	    src.close();
+	} catch (Exception e) {
+	    factory.reportMessage("Exception caught while parsing "+url+
+				  e.toString(),
+				  false);
+	}
+        return factory.parsingEnded(node);
+    }
+
+    /**
+     * A default TreeItemFactory that can be used to parse TOC items as used
+     * by this navigator.
+     */
+    public static class DefaultIndexFactory implements TreeItemFactory {
+	private Vector messages = new Vector();
+	private URL source;
+	private boolean validParse = true;
+
+	/**
+	 * Parsing has started
+	 */
+	public void parsingStarted(URL source) {
+	    if (source == null) {
+		throw new NullPointerException("source");
+	    }
+	    this.source = source;
+	}
+
+	/**
+	 * Process a DOCTYPE
+	 */
+	public void processDOCTYPE(String root, 
+				   String publicID,
+				   String systemID) {
+	    if (publicID == null ||
+		(publicID.compareTo(publicIDString) != 0 &&
+		 publicID.compareTo(publicIDString_V2) != 0)) {
+		reportMessage(HelpUtilities.getText("index.invalidIndexFormat", publicID), false);
+	    }
+	}
+
+	/**
+	 * We have found a PI; ignore it
+	 */
+	public void processPI(HelpSet hs, String target, String data) {
+	}
+
+	/**
+	 * Creates an IndexItem with the given data.
+	 * @param tagName The index type to create. 
+	 * Valid types are "indexitem". Null or invalid types throw an
+	 * IllegalArgumentException.
+	 * @param atts Attributes of the Item. Valid attributes are "target"
+	 * and "text". A null <tt>atts</tt> is valid and means no attributes.
+	 * @param hs The HelpSet this item was created under. 
+	 * @param locale Locale of this item. A null locale is valid. 
+	 * @returns A fully constructed TreeItem.
+	 * @throws IllegalArgumentException if tagname is null or invalid.
+	 */
+	public TreeItem createItem(String tagName,
+				   Hashtable atts,
+				   HelpSet hs,
+				   Locale locale) {
+	    if (tagName == null || !tagName.equals("indexitem")) {
+		throw new IllegalArgumentException("tagName");
+	    }
+	    IndexItem item = null;
+	    String id = null;
+	    String text = null;
+            String mergeType = null;
+	    String expand = null;
+	    String presentation = null;
+	    String presentationName = null;
+
+	    if (atts != null ) {
+		id = (String) atts.get("target");
+		text = (String) atts.get("text");
+                mergeType = (String) atts.get("mergetype");
+		expand = (String) atts.get("expand");
+		presentation = (String) atts.get("presentationtype");
+		presentationName = (String) atts.get("presentationname");		
+	    }
+	    
+	    try { 
+		item = new IndexItem(ID.create(id, hs),
+				     hs,
+				     locale);
+	    } catch (BadIDException ex) {
+		item = new IndexItem();
+	    }
+
+	    if (text != null) {
+		item.setName(text);
+	    }
+	    if (mergeType != null){
+		item.setMergeType(mergeType);
+	    }
+	    if (expand != null) {
+		if (expand.equals("true")) {
+		    item.setExpansionType(TreeItem.EXPAND);
+		} else if (expand.equals("false")) {
+		    item.setExpansionType(TreeItem.COLLAPSE);
+		}
+	    }
+		    
+            if (presentation != null){
+                item.setPresentation(presentation);
+            }
+
+            if (presentationName != null){
+                item.setPresentationName(presentationName);
+            }
+
+	    return item;
+	}
+	
+	/**
+	 * Creates a default IndexItem.
+	 */
+	public TreeItem createItem() {
+	    return new IndexItem();
+	}
+
+	/**
+	 * Reports an error message.
+	 */
+	public void reportMessage(String msg, boolean validParse) {
+	    messages.addElement(msg);
+	    this.validParse = this.validParse && validParse;
+	}
+
+	/**
+	 * Lists all the error messages.
+	 */
+	public Enumeration listMessages() {
+	    return messages.elements();
+	}
+
+	/**
+	 * Parsing has ended.  The last chance to do something
+	 * to the node
+	 * @param node The DefaultMutableTreeNode that has been built during the
+	 * the parsing. If <tt>node</tt> is null or there were parsing errors a null 
+	 * is returned.
+	 * @returns A valid DefaultMutableTreeNode if the parsing succeded or null
+	 * if it failed
+	 */
+	public DefaultMutableTreeNode parsingEnded(DefaultMutableTreeNode node) {
+	    DefaultMutableTreeNode back = node;
+	    if (! validParse) {
+		// A parse with problems...
+		back = null;
+                System.err.println("Parsing failed for "+source);
+		for (Enumeration e = messages.elements();
+		     e.hasMoreElements();) {
+		    String msg = (String) e.nextElement();
+		    // need to think about this one...
+                    System.err.println(msg);
+		}
+	    }
+	    return back;
+	}
+    }
+    
+
+    /**
+     * Inner class for parsing an Index stream.
+     *
+     * WARNING!! This class is an interim solution until JH moves to a
+     * real XML parser.  This is not a public class.  Clients should only use
+     * the parse method in the enclosing class.
+     */
+
+    private static class IndexParser implements ParserListener {
+	private HelpSet currentParseHS; // HelpSet we are parsing into
+	private Stack nodeStack;	// to track the parsing
+	private Stack itemStack;
+	private Stack tagStack;
+	private Locale defaultLocale;
+	private Locale lastLocale;
+	private boolean startedindex;
+	private TreeItemFactory factory;
+
+	/**
+	 * Creates an Index Parser using a factory instance to create the item nodes.
+	 *
+	 * @param factory The ItemTreeFactory instance to use when a node
+	 * has been recognized.
+	 */
+
+	IndexParser(TreeItemFactory factory) {
+	    this.factory = factory;
+	}
+
+	/**
+	 * Parse a reader into a DefaultMutableTreeNode.
+	 * Only one of these at a time.
+	 */
+	synchronized DefaultMutableTreeNode parse(Reader src,
+					   HelpSet context,
+					   Locale locale)
+	    throws IOException 
+	{
+	    nodeStack = new Stack();
+	    itemStack = new Stack();
+	    tagStack = new Stack();
+
+	    if (locale == null) {
+		defaultLocale = Locale.getDefault();
+	    } else {
+		defaultLocale = locale;
+	    }
+	    lastLocale = defaultLocale;
+
+	    DefaultMutableTreeNode node = new DefaultMutableTreeNode();
+	    nodeStack.push(node);
+	    
+	    currentParseHS = context;
+	    
+	    Parser parser = new Parser(src); // the XML parser instance
+	    parser.addParserListener(this);
+	    parser.parse();
+	    return node;
+	}
+
+	/**
+	 *  A Tag was parsed.  This method is not intended to be of general use.
+	 */
+	public void tagFound(ParserEvent e) {
+	    Locale locale = null;
+	    Tag tag = e.getTag();
+	    TagProperties attr = tag.atts;
+
+	    if (attr != null) {
+		String lang = attr.getProperty("xml:lang");
+		locale = HelpUtilities.localeFromLang(lang);
+	    }
+	    if (locale == null) {
+		locale = lastLocale;
+	    }
+
+	    if (tag.name.equals("indexitem")) {
+		if (!startedindex) {
+		    factory.reportMessage(HelpUtilities.getText("index.invalidIndexFormat"),
+					  false);
+		}
+		if (tag.isEnd && ! tag.isEmpty) {
+		    nodeStack.pop();
+		    itemStack.pop();
+		    removeTag(tag);
+		    return;
+		}
+
+		TreeItem item = null;
+		try {
+		    Hashtable t = null;
+		    if (attr != null) {
+			t = attr.getHashtable();
+		    }
+		    item = factory.createItem("indexitem",
+					      t,
+					      currentParseHS,
+					      locale);
+		} catch (Exception ex) {
+		    if (warningOfFailures) {
+			String id=null;
+			if (attr != null) {
+			    id = attr.getProperty("target");
+			}
+			System.err.println("Failure in IndexItem Creation; ");
+			System.err.println("  id: "+id);
+			System.err.println("  hs: "+currentParseHS);
+		    }
+		    item = factory.createItem();
+		}
+
+		if (!itemStack.empty()) {
+		    IndexItem parent = (IndexItem)itemStack.peek();
+		    if (item.getExpansionType() == TreeItem.DEFAULT_EXPANSION &&
+			parent != null && 
+			parent.getExpansionType() != TreeItem.DEFAULT_EXPANSION) {
+			item.setExpansionType(parent.getExpansionType());
+		    }
+		}
+		DefaultMutableTreeNode node = new DefaultMutableTreeNode(item);
+		DefaultMutableTreeNode parent = 
+		    (DefaultMutableTreeNode) nodeStack.peek();
+		parent.add(node);
+		if (! tag.isEmpty) {
+		    itemStack.push(item);
+		    nodeStack.push(node);
+		    addTag(tag, locale);
+		}
+	    }  else if (tag.name.equals("index")) {
+		if (!tag.isEnd) {
+		    if (attr != null) {
+		        String version = attr.getProperty("version");
+			if (version != null && 
+			    (version.compareTo("1.0") != 0 &&
+			     version.compareTo("2.0") != 0 )) {
+			    factory.reportMessage(HelpUtilities.getText("index.unknownVersion", version), false);
+			}
+		    }
+		    if (startedindex) {
+			factory.reportMessage(HelpUtilities.getText("index.invalidIndexFormat"),
+					      false);
+		    }
+		    startedindex = true;
+		    addTag(tag, locale);
+		} else {
+		    if (startedindex) {
+			startedindex = false;
+		    }
+		    removeTag(tag);
+		}
+		return;
+	    }
+	}
+
+	/**
+	 *  A PI was parsed.  This method is not intended to be of general use.
+	 */
+	public void piFound(ParserEvent e) {
+	    // ignore
+	}
+
+	/**
+	 *  A DOCTYPE was parsed.  This method is not intended to be of general use.
+	 */
+	public void doctypeFound(ParserEvent e) {
+	    // ignore for now
+	    factory.processDOCTYPE(e.getRoot(), e.getPublicId(), e.getSystemId());
+	}
+
+	/**
+	 * A continous block of text was parsed.
+	 */
+	public void textFound(ParserEvent e) {
+	    if (tagStack.empty()) {
+		return;		// ignore
+	    }
+	    LangElement le = (LangElement) tagStack.peek();
+	    Tag tag = (Tag) le.getTag();
+	    if (tag.name.equals("indexitem")) {
+		IndexItem item = (IndexItem) itemStack.peek();
+		String oldName = item.getName();
+		if (oldName == null) {
+		    item.setName(e.getText().trim());
+		} else {
+		    item.setName(oldName.concat(e.getText()).trim());
+		}
+	    }
+	}
+
+	// The remaing events from Parser are ignored
+	public void commentFound(ParserEvent e) {}
+
+	public void errorFound(ParserEvent e){
+	    factory.reportMessage(e.getText(), false);
+	}
+
+	/**
+	 * Keeps track of tags and their locale attributes.
+	 */
+	protected void addTag(Tag tag, Locale locale) {
+	    LangElement el = new LangElement(tag, locale);
+	    tagStack.push(el);
+	    // It's possible for lastLocale not be specified ergo null.
+	    // If it is then set lastLocale to null even if locale is null.
+	    // It is impossible for locale to be null
+	    if (lastLocale == null) {
+		lastLocale = locale;
+		return;
+	    }
+	    if (locale == null) {
+		lastLocale = locale;
+		return;
+	    }
+	    if (! lastLocale.equals(locale)) {
+		lastLocale = locale;
+	    }
+	}
+
+	/**
+	 * Removes a tag from the tagStack. The tagStack is
+	 * used to keep track of tags and locales.
+	 */
+	protected void removeTag(Tag tag) {
+	    LangElement el;
+	    String name = tag.name;
+	    Locale newLocale=null;
+
+	    for (;;) {
+		if (tagStack.empty()) 
+		    break;
+		el = (LangElement) tagStack.pop();
+		if (! el.getTag().name.equals(name)) {
+		    if (tagStack.empty()) {
+			newLocale = defaultLocale;
+		    } else {
+			el = (LangElement) tagStack.peek();
+			newLocale = el.getLocale();
+		    }
+		    break;
+		}
+	    }
+	    // It's possible for lastLocale not be specified ergo null.
+	    // If it is then set lastLocale to null even if locale is null.
+	    // It also possible for locale to be null so if lastLocale is set
+	    // then reset lastLocale to null;
+	    // Otherwise if lastLocale doesn't equal locale reset lastLocale to locale
+	    if (lastLocale == null) {
+		lastLocale = newLocale;
+		return;
+	    }
+	    if (newLocale == null) {
+		lastLocale = newLocale;
+		return;
+	    }
+	    if (! lastLocale.equals(newLocale)) {
+		lastLocale = newLocale;
+	    }
+	}
+
+    }
+
+    /**
+     * Debugging code
+     */
+    private static final boolean debug = false;
+    private static void debug(String msg) {
+  	if (debug) {
+  	    System.err.println("IndexView: "+msg);
+	}
+    }
+
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/InvalidHelpSetContextException.java b/jhMaster/JavaHelp/src/new/javax/help/InvalidHelpSetContextException.java
new file mode 100644
index 0000000000000000000000000000000000000000..e0dda7932d9628a2ed78af3f65a8a1e42dc02a6d
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/InvalidHelpSetContextException.java
@@ -0,0 +1,69 @@
+/*
+ * @(#)InvalidHelpSetContextException.java	1.6 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help;
+
+/**
+ * The HelpSet is not a (transitive) sub-HelpSet of some context HelpSet.
+ *
+ * For example, setting an ID to a HelpModel.
+ *
+ * @author Eduardo Pelegri-Llopart
+ * @version	1.3	01/29/99
+ */
+public class InvalidHelpSetContextException extends Exception {
+    private HelpSet context;
+    private HelpSet hs;
+
+    /**
+     * Create the exception. All parameters accept null values.
+     * 
+     * @param msg The message. If msg is null it is the same as if
+     * no detailed message was specified.
+     */
+    public InvalidHelpSetContextException(String msg,
+					  HelpSet context,
+					  HelpSet hs) {
+	super(msg);
+	this.context = context;
+	this.hs = hs;
+    }
+
+    /**
+     * Get the context HelpSet
+     */
+    public HelpSet getContext() {
+	return context;
+    }
+
+    /**
+     * Get the offending HelpSet
+     */
+    public HelpSet getHelpSet() {
+	return hs;
+    }
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/InvalidNavigatorViewException.java b/jhMaster/JavaHelp/src/new/javax/help/InvalidNavigatorViewException.java
new file mode 100644
index 0000000000000000000000000000000000000000..577093c90103e94f7a1c9e361c2fe6472b3709a3
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/InvalidNavigatorViewException.java
@@ -0,0 +1,112 @@
+/*
+ * @(#)InvalidNavigatorViewException.java	1.14 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help;
+
+import java.util.Hashtable;
+import java.util.Locale;
+
+/**
+ * JHelpNavigator cannot deal with given NavigatorView.
+ *
+ * @author Eduardo Pelegri-Llopart
+ * @version	1.14	10/30/06
+ */
+
+public class InvalidNavigatorViewException extends Exception 
+{
+    /**
+     * Create an exception. All parameters accept null values.
+     * 
+     * @param msg The message. If msg is null it is the same as if
+     * no detailed message was specified.
+     */
+    public InvalidNavigatorViewException(String msg,
+					 HelpSet hs,
+					 String name,
+					 String label,
+					 Locale locale,
+					 String className,
+					 Hashtable params) {
+	super(msg);
+	this.hs = hs;
+	this.name = name;
+	this.label = label;
+	this.locale = locale;
+	this.className = className;
+	this.params = params;
+    }
+
+    /**
+     * @return The helpset
+     */
+    public HelpSet getHelpSet() {
+	return hs;
+    }
+
+    /**
+     * @return The name
+     */
+    public String getName() {
+	return name;
+    }
+
+    /**
+     * @return The label
+     */
+    public String getLabel() {
+	return label;
+    }
+
+    /**
+     * @return The locale
+     */
+    public Locale getLocale() {
+	return locale;
+    }
+
+    /**
+     * @return The className
+     */
+    public String getClassName() {
+	return className;
+    }
+
+    /**
+     * @return The parameters
+     */
+    public Hashtable getParams() {
+	return params;
+    }
+
+    private HelpSet hs;
+    private String name;
+    private String label;
+    private Locale locale;
+    private String className;
+    private Hashtable params;
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/JHelp.java b/jhMaster/JavaHelp/src/new/javax/help/JHelp.java
new file mode 100644
index 0000000000000000000000000000000000000000..4c946f933c16e22ed348084454db0e554c09a63d
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/JHelp.java
@@ -0,0 +1,678 @@
+/*
+ * @(#)JHelp.java	1.78 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+
+package javax.help;
+
+import java.net.URL;
+import javax.swing.JComponent;
+import javax.swing.UIManager;
+import javax.swing.LookAndFeel;
+import javax.accessibility.*;
+import java.util.Vector;
+import java.util.Enumeration;
+import java.util.EventListener;
+import java.util.Locale;
+import java.io.InputStream;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import javax.help.plaf.HelpUI;
+import javax.help.event.HelpSetListener;
+import javax.help.event.HelpSetEvent;
+import javax.help.Map.ID;
+
+/**
+ * Displays HelpSet data with navigators and a content viewer.
+ *
+ * @author Roger D. Brinkley
+ * @author Eduardo Pelegri-Llopart
+ * @author Stepan Marek
+ * @author Richard Gregor
+ * @version	1.78	10/30/06
+ */
+public class JHelp extends JComponent implements HelpSetListener, Accessible {
+    protected TextHelpModel helpModel;
+    protected HelpHistoryModel historyModel;
+    protected Vector navigators;
+    protected boolean navDisplayed=true;
+    protected boolean toolbarDisplayed=true;
+    protected HelpSet.Presentation hsPres;
+
+    protected JHelpContentViewer contentViewer;
+    
+
+    /**
+     * Create a JHelp with a JHelpContentViewer and all Navigators 
+     * requested in the HelpSet.
+     *
+     * @param hs The HelpSet. If hs is null the JHelp is created with a 
+     * TextHelpModel with no HelpSet.
+     */
+    public JHelp(HelpSet hs) {
+	this(new DefaultHelpModel(hs), 
+	     null, 
+	     hs==null? null : hs.getDefaultPresentation());
+    }
+    
+    /**
+     * Create a JHelp component without a TextHelpModel.
+     */
+    public JHelp() {
+	this((TextHelpModel)null);
+    }
+
+    /**
+     * Create a JHelp using the TextHelpModel.
+     *
+     * @param model A model to use for the content and all the navigators. If <tt>model</tt>
+     * is null it is the same as creating without a TextHelpModel
+     */
+    public JHelp(TextHelpModel model){
+        this(model, null, null);
+    }
+    
+    /**
+     * Create a JHelp using the TextHelpModel and HelpHistoryModel
+     *
+     * @param model A model to use for the content and all the navigators. If <tt>model</tt>
+     * is null it is the same as creating without a TextHelpModel
+     * @param history A history model. If <<tt>history</tt> is null it is the same
+     * as creating without HelpHistoryModel
+     */
+    public JHelp(TextHelpModel model, HelpHistoryModel history, 
+		 HelpSet.Presentation hsPres){
+        super();
+        
+        if(history == null)
+            this.historyModel = new DefaultHelpHistoryModel(this);
+        else
+            this.historyModel = history;
+
+	this.hsPres = hsPres;
+        
+        navigators = new Vector();
+	navDisplayed = true;
+
+	// HERE -- need to do something about doc title changes....
+
+	this.contentViewer = new JHelpContentViewer(model);
+
+	setModel(model);
+	if (model != null) {
+	    setupNavigators();            
+        }
+
+        updateUI();
+    }
+
+    protected void setupNavigators() {
+	HelpSet hs = helpModel.getHelpSet();
+	// Simply return if the hs is null
+	if (hs == null) {
+	    return;
+	}
+
+	// Now add all the navigators
+	NavigatorView views[] = hs.getNavigatorViews();
+
+	debug("views: "+views);
+
+	for (int i=0; i<views.length; i++) {
+	    debug("  processing info: "+views[i]);
+
+	    // We are currently assuming all the Navigators are JComponents
+	    JHelpNavigator nav
+		= (JHelpNavigator) views[i].createNavigator(helpModel);
+	    
+	    if (nav == null) {
+		// For now...
+		debug("no JHelpNavigator for given info");
+	    } else {
+		debug("  adding the navigator");
+		navigators.addElement(nav);
+		// HERE -- I don't think we want to change again the model
+		//		    this.addHelpNavigator(nav);
+            }
+	}
+    }
+    
+    /**
+     * Sets the HelpModel that provides the data.
+     *
+     * @param newModel The new Model. If <tt>newModel</tt> is null the internal model is set
+     * to null.
+     */
+    public void setModel(TextHelpModel newModel) {
+	TextHelpModel oldModel = helpModel;
+        if (newModel != oldModel) {
+	    if (oldModel != null) {
+                oldModel.getHelpSet().removeHelpSetListener(this);
+	    }
+            helpModel = newModel;
+	    if (newModel != null) {                
+		HelpSet hs = newModel.getHelpSet();
+		if (hs != null) {
+		    hs.addHelpSetListener(this);
+		}
+	    }
+            firePropertyChange("helpModel", oldModel, helpModel);
+
+	    // Now tell all the components we control
+	    contentViewer.setModel((TextHelpModel) newModel);
+            
+            getHistoryModel().setHelpModel((HelpModel) newModel);
+
+	    // We'll have to destroy all of the navigators and
+	    // reload them from the HelpSet
+	    HelpUI help = getUI();
+
+	    // Skip the navigators if the ui hasn't been setup yet.
+	    if (help == null) {
+		return;
+	    }
+
+	    for (Enumeration e = getHelpNavigators();
+		 e.hasMoreElements(); ) {
+		JHelpNavigator nav = (JHelpNavigator) e.nextElement();
+		help.removeNavigator(nav);
+	    }
+	    navigators.removeAllElements();
+	    setupNavigators();
+	    updateUI();
+        }
+    }
+
+    /**
+     * @return The HelpModel that is providing the data.
+     */
+    public TextHelpModel getModel() {
+	return helpModel;
+    }
+
+    /**
+     * Returns The HelpHistoryModel
+     *
+     * @return The HelpHistoryModel which provides history data
+     */
+    public HelpHistoryModel getHistoryModel(){
+        return historyModel;
+    }
+
+    /**
+     * Set the HelpSet.Presentation.
+     * @see HelpSet.Presentation
+     */
+    public void setHelpSetPresentation(HelpSet.Presentation hsPres) {
+	this.hsPres = hsPres;
+	return;
+    }
+
+
+    /**
+     * @return The HelpSet.Presentation.
+     * @see HelpSet.Presentation
+     */
+    public HelpSet.Presentation getHelpSetPresentation() {
+	return hsPres;
+    }
+
+
+    // HERE - need customizers, etc... -epll
+    // HERE - this is probably broken
+    /**
+     * Set the URL to the HelpSet.  This forces the HelpSet to be reloaded.
+     *
+     * @param spec Where to locate the HelpSet. A null spec is valid
+     */
+    public void setHelpSetSpec(String spec) {
+	URL url;
+	HelpSet hs;
+	ClassLoader loader = this.getClass().getClassLoader();
+	try {
+	    url = new URL(spec);
+	    hs = new HelpSet(loader, url);
+	} catch (Exception ex) {
+	    System.err.println("Trouble setting HelpSetSpec to spec |"+spec+"|");
+	    System.err.println("  ex: "+ex);
+	    hs = null;
+	}
+	contentViewer.setModel(new DefaultHelpModel(hs));
+	setModel(contentViewer.getModel());
+	updateUI();
+    }
+
+    /**
+     * @return The URL to the HelpSet.
+     */
+    public URL getHelpSetURL() {
+	HelpSet hs = contentViewer.getModel().getHelpSet();
+	if (hs == null) {
+	    return null;
+	}
+	return hs.getHelpSetURL();
+    }
+
+    // === The JComponent methods
+
+    /**
+     * Sets the HelpUI that will provide the current look and feel.
+     * @param ui The HelpUI to set for this component. A null value for ui
+     * is valid.
+     */
+    public void setUI(HelpUI ui) {
+	if ((HelpUI)this.ui != ui) {
+	    super.setUI(ui);
+	}
+    }
+
+    /**
+     * Returns the HelpUI that is providing the current look and feel.
+     */
+    public HelpUI getUI() {
+	return (HelpUI)ui;
+    }
+
+    /**
+     * Replaces the UI with the latest version from the default 
+     * UIFactory.
+     *
+     * @overrides updateUI in class JComponent
+     */
+    public void updateUI() {
+        SwingHelpUtilities.installUIDefaults();
+        setUI((HelpUI)UIManager.getUI(this));
+        invalidate();
+    }
+
+    /**
+     * @return "HelpUI"
+     */
+    public String getUIClassID()
+    {
+        return "HelpUI";
+    }
+
+    /*
+     * Findd the navigator with a given name.
+     */
+    private JHelpNavigator findNavigator(String name) {
+	debug("findNavigator("+name+")");
+	for (Enumeration e = getHelpNavigators();
+	     e.hasMoreElements(); ) {
+	    JHelpNavigator nav = (JHelpNavigator) e.nextElement();
+	    debug("  nav: "+nav);
+	    debug("  nav.getName: "+nav.getNavigatorName());
+	    if (nav.getNavigatorName().equals(name)) {
+		return nav;
+	    }
+	}
+	return null;
+    }
+
+    /**
+     * Adds a new HelpSet to "our" HelpSet.
+     *
+     * @param e HelpSetEvent
+     * @see javax.help.event.HelpSetEvent
+     * @see javax.help.event.HelpSetListener
+     */
+    public void helpSetAdded(HelpSetEvent e) {
+	debug("helpSetAdded("+e+")");
+	HelpSet ehs = e.getHelpSet();
+	addHelpSet(ehs);
+    }
+    
+    /*
+     * Adds a HelpSet.
+     */
+    private void addHelpSet(HelpSet ehs) {
+        debug("helpset :"+ehs);
+	NavigatorView eviews[] = ehs.getNavigatorViews();
+        
+        //if master help set is created using new HelpSet() -without arguments it hasn't got any navigators to merge
+        //we will create new navigators
+
+        int count = 0;
+        for (Enumeration e = getHelpNavigators() ; e.hasMoreElements() ;e.nextElement()) {
+            ++count;
+        }
+        if(count == 0){
+            debug("master helpset without navigators");            
+            HelpModel newModel= new DefaultHelpModel(ehs);
+            setModel((TextHelpModel)newModel);
+            setupNavigators();
+            return;
+        }
+        
+             
+    	for (int i=0; i<eviews.length; i++) {
+	    String n = eviews[i].getName();
+	    debug("addHelpSet: looking for navigator for "+n);
+	    JHelpNavigator nav = findNavigator(n);
+	    if (nav != null) {
+		debug("   found");
+		if (nav.canMerge(eviews[i])) {
+		    debug("  canMerge: true; merging...");
+		    nav.merge(eviews[i]);
+		} else {
+		    debug("  canMerge: false");
+		}
+	    } else {
+		debug("   not found");
+	    }
+	}
+	// In this version, we can only add views that appear at the top
+    }
+
+    /**
+     * Removes a HelpSet from "our" HelpSet.
+     */
+    public void helpSetRemoved(HelpSetEvent e) {
+	debug("helpSetRemoved("+e+")");
+	HelpSet ehs = e.getHelpSet();
+	removeHelpSet(ehs);
+    }
+
+    private void removeHelpSet(HelpSet ehs) {
+	NavigatorView eviews[] = ehs.getNavigatorViews();
+
+	for (int i=0; i<eviews.length; i++) {
+	    String n = eviews[i].getName();
+	    debug("removeHelpSet: looking for navigator for "+n);
+	    JHelpNavigator nav = findNavigator(n);
+	    if (nav != null) {
+		debug("   found");
+		if (nav.canMerge(eviews[i])) {
+		    debug("  canMerge: true; removing...");
+		    nav.remove(eviews[i]);
+		} else {
+		    debug("  canMerge: false");
+		}
+	    } else {
+		debug("   not found");
+	    }
+	}
+        
+        // set the last displayed URL from Help. Set other than removed HelpSet, recount history 
+        //helpModel.removeFromHistory(ehs);               
+        //firePropertyChange("removeHelpSet",null,ehs);
+        getHistoryModel().removeHelpSet(ehs);
+    }
+
+    /**
+     * Visits a given ID.  Propagates down into the model.
+     *
+     * @param id The ID to visit. Null id is valid for TextHelpModel.setCurrentID.
+     * @exception InvalidHelpSetContextException if id.hs is not contained in getHelpSet()
+     */
+    public void setCurrentID(ID id) throws InvalidHelpSetContextException {
+	if (helpModel != null) {
+	    helpModel.setCurrentID(id);
+	}
+    }
+    
+    /**
+     * Visits a given ID.  Propagates down into the model.
+     *
+     * @param id The ID to visit. Null id is valid for TextHelpModel.setCurrentID.
+     * @param historyName The name for history entry
+     * @param navigator The JHelpNavigator
+     * @exception InvalidHelpSetContextException if id.hs is not contained in getHelpSet()
+     */ 
+    public void setCurrentID(ID id, String historyName, JHelpNavigator navigator)throws InvalidHelpSetContextException{
+        if (helpModel != null) {
+	    helpModel.setCurrentID(id,historyName,navigator);
+	}
+    }
+        
+    /**
+     * Convenience version of the above. The implicit HelpSet is
+     * the current HelpSet.
+     *
+     * @param id The String to visit. Null id is valid for TextHelpModel.setCurrentID.
+     * @exception BadIDException if the string is not in the map for the HelpSet.
+     */
+    public void setCurrentID(String id) throws BadIDException {
+	try {
+	    helpModel.setCurrentID(ID.create(id, getModel().getHelpSet()));
+	} catch (InvalidHelpSetContextException ex) {
+	    // cannot happen
+	}
+    }
+
+    /**
+     * Visits a given URL.  Propagates down into the model.
+     *
+     * @param url The URL to visit
+     */
+    public void setCurrentURL(URL url) {
+	helpModel.setCurrentURL(url);
+    }
+    
+    /**
+     * Visits a given URL.  Propagates down into the model.
+     *
+     * @param url The URL to visit
+     */
+    public void setCurrentURL(URL url, String historyName, JHelpNavigator navigator) {
+	helpModel.setCurrentURL(url, historyName, navigator);
+    }
+
+    /**
+     * Returns a list of selected items from the current navigator
+     */
+    public TreeItem[] getSelectedItems() {
+	    return getCurrentNavigator().getSelectedItems();
+    }
+
+    /**
+     * Sets the list of selected items
+     */
+    /*
+    public void setSelectedItems(TreeItem[] selectedItems) {
+        getCurrentNavigator().setSelectedItems(selectedItems);
+	firePropertyChange("SelectedItemsChangedProperty", oldValue, this.selectedItems);
+    }
+     */
+
+    /**
+     * A JHelp can have a number of navigators.
+     * One of navigators is active.
+     * How they are presented depends on the UI, but they may be a collection
+     * of tabs, with the active tab being at the front.
+     * <br>
+     * Each navigator listens to changes to the HelpModel.
+     * A navigator can also tell the model to change--the change
+     * is propagated to the other navigators, this component, and
+     * the content viewer if they all use the same
+     * HelpModel instance.
+     *
+     * @param navigator The Navigator to explicitly add to the JHelp.
+     */
+    public void addHelpNavigator(JHelpNavigator navigator) {
+	debug("addHelpNavigator("+navigator+")");
+	navigators.addElement(navigator);
+	HelpUI help = getUI();
+	help.addNavigator(navigator);
+	
+	// force a common model
+	navigator.setModel(getModel());
+    }
+
+    /**
+     * Removes a navigator.
+     *
+     * @param navigator The Navigator to explicitly add to the JHelp. 
+     */
+    public void removeHelpNavigator(JHelpNavigator navigator) {
+	debug("removeHelpNavigator("+navigator+")");
+	if (navigator == null) {
+	    throw new NullPointerException("navigator");
+	}
+	navigators.removeElement(navigator);
+	HelpUI help = getUI();
+	help.removeNavigator(navigator);
+    }
+
+    /**
+     * @return An Enumeration of HelpNavigators in the HelpUI.
+     */
+    public Enumeration getHelpNavigators() {
+	return navigators.elements();
+    }
+
+    /**
+     * Sets the current navigator in the HelpUI.
+     *
+     * @param navigator The navigator
+     * @exception throws InvalidNavigatorException if not a one of HELPUI
+     *   navigators.
+     */
+    public void setCurrentNavigator(JHelpNavigator navigator) {
+	HelpUI help = getUI();
+	help.setCurrentNavigator(navigator);
+    }
+
+    /**
+     * @return The current navigator in the HelpUI
+     */
+    public JHelpNavigator getCurrentNavigator() {
+	HelpUI help = getUI();
+	return help.getCurrentNavigator();
+    }
+
+    /**
+     * Hidess/Displays the Navigators in the HelpUI.
+     *
+     * @displayed Whether to display or not
+     */
+    public void setNavigatorDisplayed(boolean displayed) {
+	if (navDisplayed != displayed) {
+	    navDisplayed = displayed;
+	    firePropertyChange("navigatorDisplayed", !displayed, displayed);
+	}
+    }
+
+    /**
+     * Determines if the Navigators are hidden/displayed in the HelpUI.
+     *
+     * @return Are the navigators displayed?
+     * @since 2.0
+     */
+    public boolean isNavigatorDisplayed() {
+	return navDisplayed;
+    }
+
+    /**
+     * Hidess/Displays the Toolbar in the HelpUI.
+     *
+     * @displayed Whether to display or not
+     * @since 2.0
+     */
+    public void setToolbarDisplayed(boolean displayed) {
+	if (toolbarDisplayed != displayed) {
+	    toolbarDisplayed = displayed;
+	    firePropertyChange("toolbarDisplayed", !displayed, displayed);
+	}
+    }
+
+    /**
+     * Determines if the Navigators are hidden/displayed in the HelpUI.
+     *
+     * @return is the toolbar displayed?
+     * @since 2.0
+     */
+    public boolean isToolbarDisplayed() {
+	return toolbarDisplayed;
+    }
+
+    /**
+     * Retrieves what is the current content viewer
+     * Read-Only property?
+     */
+    public JHelpContentViewer getContentViewer() {
+	return contentViewer;
+    }
+
+    /**
+     * Debug code
+     */
+
+    private boolean debug = false;
+    private void debug(String msg) {
+	if (debug) {
+	    System.err.println("JHelp: "+msg);
+	}
+    }
+
+    /*
+     * Make sure the Look and Feel will be set for the Help Component
+     */
+    static {
+	SwingHelpUtilities.installLookAndFeelDefaults();
+    }
+
+/////////////////
+// Accessibility support
+////////////////
+
+    /**
+     * Get the AccessibleContext associated with this JComponent.
+     *
+     * @return The AccessibleContext of this JComponent
+     */
+    public AccessibleContext getAccessibleContext() {
+        if (accessibleContext == null) {
+            accessibleContext = new AccessibleJHelp();
+        }
+        return accessibleContext;
+    }
+
+    /**
+     * The class used to obtain the accessible role for this object.
+     * <p>
+     * <strong>Warning:</strong>
+     * Serialized objects of this class will not be compatible with
+     * future Swing releases.  The current serialization support is appropriate
+     * for short term storage or RMI between applications running the same
+     * version of Swing.  A future release of Swing will provide support for
+     * long term persistence.
+     */
+    protected class AccessibleJHelp extends AccessibleJComponent {
+
+        /**
+         * Get the role of this object.
+         *
+         * @return an instance of AccessibleRole describing the role of the
+         * object
+         */
+        public AccessibleRole getAccessibleRole() {
+            return AccessibleRole.PANEL;
+        }
+    }
+}
+
diff --git a/jhMaster/JavaHelp/src/new/javax/help/JHelpContentViewer.java b/jhMaster/JavaHelp/src/new/javax/help/JHelpContentViewer.java
new file mode 100644
index 0000000000000000000000000000000000000000..2f9b7aac3379da5d98869af9c4fc1c0ea1021786
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/JHelpContentViewer.java
@@ -0,0 +1,425 @@
+/*
+ * @(#)JHelpContentViewer.java	1.34 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help;
+
+import java.net.URL;
+import javax.swing.JComponent;
+import javax.swing.UIManager;
+import javax.swing.LookAndFeel;
+import javax.swing.JEditorPane;
+import javax.accessibility.*;
+import java.util.Hashtable;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import javax.help.event.*;
+import javax.help.plaf.HelpContentViewerUI;
+import javax.swing.text.EditorKit;
+import javax.help.Map.ID;
+
+/**
+ * A component to represent the Help viewer that can be embedded if desired.
+ *
+ * @author Eduardo Pelegri-Llopart
+ * @version   1.34     10/30/06
+ */
+public class JHelpContentViewer extends JComponent implements Accessible{
+    protected TextHelpModel model;
+    /**
+     * Mark this JHelpContentViewer as synchronized with navigators
+     * It is false for JHelpContentviewer used inside of glossary
+     */
+    private boolean synch = true;
+
+    /**
+     * Creates a JHelp with an instance of DefaultHelpModel as its data model.
+     *
+     * @param hs The HelpSet that provides context information. A null hs is valid
+     * and creates a TextHelpModel with no HelpSet defined.
+     */
+    public JHelpContentViewer(HelpSet hs) {
+	super();
+	setModel(new DefaultHelpModel(hs));
+	updateUI();
+    }
+    
+    /**
+     * Creates a JHelp with a default TextHelpModel.
+     */
+    public JHelpContentViewer() {
+	super();
+	setModel(new DefaultHelpModel(null)); // no HelpSet here!
+	updateUI();
+    }
+
+    /**
+     * Creates a JHelp with an specific TextHelpModel as its data model.
+     *
+     * @param model The TextHelpModel. A null model is valid.
+     */
+    public JHelpContentViewer(TextHelpModel model) {
+	super();
+	setModel(model);
+	updateUI();
+    }
+    
+    /**
+     * Sets the HelpModel that provides the data.
+     * Necessary to convert navigation action into visits...
+     *
+     * @param newModel The new Model to provide events for this viewer.
+     */
+    public void setModel(TextHelpModel newModel) {
+	debug("setModel: "+newModel);
+	TextHelpModel oldModel = model;
+        if (newModel != oldModel) {
+            model = newModel;
+            firePropertyChange("helpModel", oldModel, model);
+            invalidate();
+        }
+    }
+    /**
+     * @return The HelpModel that provides the events.
+     */
+    public TextHelpModel getModel() {
+	return model;
+    }
+
+    /**
+     * Sets the HelpViewerUI that provides the current look and feel.
+     *
+     * @param ui Provides the ComponentUI object. A null ui is valid.
+     */
+    public void setUI(HelpContentViewerUI ui) {
+	debug("setUI");
+	if ((HelpContentViewerUI)this.ui != ui) {
+	    super.setUI(ui);
+	    repaint();
+	}
+    }
+
+    /**
+     * @return The HelpViewerUI that provides the current look and feel.
+     */
+    public HelpContentViewerUI getUI() {
+	return (HelpContentViewerUI)ui;
+    }
+
+    /**
+     * Replaces the UI with the latest version from the default 
+     * UIFactory.
+     *
+     * @overrides updateUI in class JComponent
+     */
+    public void updateUI() {
+        SwingHelpUtilities.installUIDefaults();
+	setUI((HelpContentViewerUI)UIManager.getUI(this));
+        invalidate();
+    }
+
+    /**
+     * @return "HelpViewerUI"
+     */
+    public String getUIClassID()
+    {
+        return "HelpContentViewerUI";
+    }
+
+    /*
+     * Make sure the Look and Feel is set for the Help Component.
+     */
+    static {
+	SwingHelpUtilities.installLookAndFeelDefaults();
+    }
+
+    /**
+     * Visits a given ID.  Propagates down into the model.
+     *
+     * @param id The ID to visit.
+     * @exception InvalidHelpSetContextException if id.hs is not contained in the
+     * HelpSet of the current model.
+     */
+    public void setCurrentID(ID id) throws InvalidHelpSetContextException {
+	model.setCurrentID(id);
+    }
+
+    /**
+     * Visits a given ID.  Propagates down into the model.
+     *
+     * @param id The String to visit.  Relative to the HS of the current model.
+     * @exception BadIDException The ID is not valid for the HelpSet for the current model.
+     */
+    public void setCurrentID(String id) throws BadIDException {
+	try {
+	    model.setCurrentID(ID.create(id, getModel().getHelpSet()));
+	} catch (InvalidHelpSetContextException ex) {
+	    // cannot happen
+	}
+    }
+
+    /**
+     * Visits a given URL.  Propagates down into the model.
+     *
+     * @param url The URL to visit.  Relative to the HS of the current model
+     */
+    public void setCurrentURL(URL url) {
+	model.setCurrentURL(url);
+    }
+
+    /**
+     * @return The URL currently being presented in the viewer.
+     */
+    public URL getCurrentURL() {
+	return model.getCurrentURL();
+    }
+
+    /**
+     * @return The document title.
+     */
+
+    public String getDocumentTitle() {
+	return model.getDocumentTitle();
+    }
+
+    /**
+     * Hightlights a section of the current document from p0 to p1.
+     *
+     * @param p0 Starting position.
+     * @param p1 Ending position.
+     */
+    public void addHighlight(int p0, int p1) {
+	model.addHighlight(p0,p1);
+    }
+
+    /**
+     * Removes any Highlights.
+     */
+    public void removeAllHighlights() {
+	model.removeAllHighlights();
+    }
+    
+    /**
+     * Sets synchronization of this JHelpContentViewer with navigators.
+     * If true then JHelpContentViewer will contain homeID page when comes up at first time. 
+     * False value causes blank page in this case. 
+     */
+    public void setSynch(boolean value){
+        synch = value;
+    }
+    /**
+     * Returns synchronization mode
+     */
+    public boolean getSynch(){
+        return synch;
+    }   
+
+    /**
+     * The local kitRegistry, indexed by mime type.
+     */
+    private Hashtable kitRegistry;
+
+    /*
+     * Creation of EditorKits.
+     * This is similar to the registry used in JEditorPane, except:
+     * <p>
+     * (1) A separate registry is used so as to not interfere with other uses of JEditorPane
+     * <br>
+     * (2) The registry is centered around a HelpSet
+     */
+
+    /**
+     * Creates a handler for the given type from the registry of editor kits.
+     * If the registered class has not yet been loaded, an attempt
+     * is made to dynamically load the prototype of the kit for the
+     * given type.  If the type was registered with a ClassLoader,
+     * that ClassLoader is used to load the prototype.  If there
+     * was no registered ClassLoader, the ClassLoader for the HelpSet
+     * is used to load the prototype.
+     * <p>
+     * Once a prototype EditorKit instance is successfully located,
+     * it is cloned and the clone is returned.
+     *
+     * @param type the content type
+     * @return the editor kit, or null if one cannot be created
+     */
+    public EditorKit createEditorKitForContentType(String type) {
+        EditorKit k = null;
+        if (kitRegistry == null) {
+            // nothing has been loaded yet.
+            kitRegistry = new Hashtable();
+        } else {
+            k = (EditorKit) kitRegistry.get(type);
+        }
+        if (k == null) {
+            // try to dynamically load the support 
+	    HelpSet hs = model.getHelpSet();
+            String classname =
+		(String) hs.getKeyData(HelpSet.kitTypeRegistry,
+				       type);
+	    // I don't know of a class for this type
+	    if (classname == null) {
+		return null;
+	    }
+	    ClassLoader loader =
+		(ClassLoader) hs.getKeyData(HelpSet.kitLoaderRegistry,
+					    type);
+	    if (loader == null) {
+		loader = hs.getLoader();
+	    }
+            try {
+		Class c;
+		if (loader != null) {
+		    c = loader.loadClass(classname);
+		} else {
+		    c = Class.forName(classname);
+		}
+                k = (EditorKit) c.newInstance();
+                kitRegistry.put(type, k);
+            } catch (Throwable e) {
+                e.printStackTrace();
+                k = null;
+            }
+        }
+
+        // create a copy of the prototype or null if there
+        // is no prototype.
+        if (k != null) {
+            return (EditorKit) k.clone();
+        } else {
+	    // null, check the JEditorPane registry
+	    k = JEditorPane.createEditorKitForContentType(type);
+	}
+        return k;
+    }
+
+    /**
+     * Adds a listener for the TExtHelpModelEvent posted after the model has
+     * changed.
+     * 
+     * @param l - The listener to add.
+     * @see javax.help.TextHelpModel#removeHelpModelListener
+     */
+    public void addTextHelpModelListener(TextHelpModelListener l) {
+	getModel().addTextHelpModelListener(l);
+    }
+
+    /**
+     * Removes a listener previously added with <tt>addTextHelpModelListener</tt>
+     *
+     * @param l - The listener to remove.
+     * @see javax.help.TextHelpModel#addTextHelpModelListener
+     */
+    public void removeHelpModelListener(TextHelpModelListener l) {
+	getModel().removeTextHelpModelListener(l);
+    }
+
+    /**
+     * Adds a listener for the HelpModelEvent posted after the model has
+     * changed.
+     * 
+     * @param l - The listener to add.
+     * @see javax.help.HelpModel#removeHelpModelListener
+     */
+    public void addHelpModelListener(HelpModelListener l) {
+	getModel().addHelpModelListener(l);
+    }
+
+    /**
+     * Removes a listener previously added with <tt>addHelpModelListener</tt>
+     *
+     * @param l - The listener to remove.
+     * @see javax.help.HelpModel#addHelpModelListener
+     */
+    public void removeHelpModelListener(HelpModelListener l) {
+	getModel().removeHelpModelListener(l);
+    }
+
+    /**
+     * Cleans the content
+     */
+    public void clear(){
+        firePropertyChange("clear", " ","xyz");
+    }
+        
+    /**
+     * Reloads the content
+     */
+    public void reload(){
+        firePropertyChange("reload", " ","xyz");
+    }
+        
+    
+    /**
+     * Debug code
+     */
+    private boolean debug = false;
+    private void debug(String msg) {
+	if (debug) {
+	    System.err.println("JHelpContentViewer: "+msg);
+	}
+    }
+
+/////////////////
+// Accessibility support
+////////////////
+
+    /**
+     * Get the AccessibleContext associated with this JComponent
+     *
+     * @return the AccessibleContext of this JComponent
+     */
+    public AccessibleContext getAccessibleContext() {
+        if (accessibleContext == null) {
+            accessibleContext = new AccessibleJHelpContentViewer();
+        }
+        return accessibleContext;
+    }
+
+    /**
+     * The class used to obtain the accessible role for this object.
+     * <p>
+     * <strong>Warning:</strong>
+     * Serialized objects of this class will not be compatible with
+     * future Swing releases.  The current serialization support is appropriate
+     * for short term storage or RMI between applications running the same
+     * version of Swing.  A future release of Swing will provide support for
+     * long term persistence.
+     */
+    protected class AccessibleJHelpContentViewer extends AccessibleJComponent {
+
+        /**
+         * Get the role of this object.
+         *
+         * @return an instance of AccessibleRole describing the role of the
+         * object
+         */
+        public AccessibleRole getAccessibleRole() {
+            return AccessibleRole.PANEL;
+        }
+    }
+}
+
diff --git a/jhMaster/JavaHelp/src/new/javax/help/JHelpFavoritesNavigator.java b/jhMaster/JavaHelp/src/new/javax/help/JHelpFavoritesNavigator.java
new file mode 100644
index 0000000000000000000000000000000000000000..ada12fb956c3c1801ac934979efb4e453b5bf714
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/JHelpFavoritesNavigator.java
@@ -0,0 +1,137 @@
+/*
+ * @(#)JHelpFavoritesNavigator.java	1.4 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help;
+
+import java.net.URL;
+import javax.swing.event.ChangeListener;
+import javax.swing.event.ChangeEvent;
+import javax.swing.Action;
+
+/**
+ * JHelpFavoritesNavigator is a JHelpNavigator for Favorites.
+ *
+ * All the tree navigation and selection has been delegated to the UI
+ * where the JTree is created.
+ *
+ * @author Richard Gregor
+ * @version   1.4     10/30/06
+ */
+public class JHelpFavoritesNavigator extends JHelpNavigator {
+    
+    /**
+     * Creates an Index navigator.
+     *
+     * @param view The NavigatorView
+     */
+    public JHelpFavoritesNavigator(NavigatorView view) {
+        super(view, null);
+    }
+    
+    /**
+     * Creates a Index navigator.
+     *
+     * @param view The NavigatorView.
+     * @param model The model for the Navigator.
+     */
+    public JHelpFavoritesNavigator(NavigatorView view, HelpModel model) {
+        super(view, model);
+    }
+            
+    // HERE - label & Locale?
+    // HERE - URL data vs Hashtable?
+    /**
+     * Creates an Index navigator with explicit arguments.  Note that this should not throw
+     * an InvalidNavigatorViewException since we are implicitly passing the type.
+     *
+     * @param hs HelpSet
+     * @param name The name identifying this HelpSet.
+     * @param label The label to use (for this locale).
+     * @param data The "data" part of the parameters, a URL location of the TOC data.
+     */
+    public JHelpFavoritesNavigator(HelpSet hs,
+    String name, String label, URL data)
+    throws InvalidNavigatorViewException {
+        super(new FavoritesView(hs, name, label, createParams(data)));
+    }
+    
+    /**
+     * Gets the UID for this JComponent.
+     */
+    public String getUIClassID() {
+        return "HelpFavoritesNavigatorUI";
+    }
+    
+    /**
+     * Determines if this instance of a JHelpNavigator can merge its data with another one.
+     *
+     * @param view The data to merge
+     * @return Whether it can be merged
+     *
+     * @see merge(NavigatorView)
+     * @see remove(NavigatorView)
+     */
+    public boolean canMerge(NavigatorView view) {
+        return false;
+    }
+     
+    /**
+     * Sets state of navigation entry for given target to expanded. Non-empty entry is expanded. Empty entry is visible.
+     *
+     * @param target The target to expand
+     */
+    public void expandID(String target){
+        firePropertyChange("expand"," ",target);
+    }
+    
+    /**
+     * Sets state of navigation entry for given target to collapsed if entry is visible. Parent is collapsed if entry is empty.
+     *
+     * @param target The target to collapse
+     */
+    public void collapseID(String target){
+        firePropertyChange("collapse"," ",target);
+    }
+    
+    /**
+     * Returns an AddAction object for this navigator
+     *
+     */
+    public Action getAddAction(){
+        return this.getUI().getAddAction();
+    }
+    
+    private static final boolean debug = false;
+    private static void debug(String msg) {
+        if (debug) {
+            System.err.println("JHelpIndexNavigator: "+msg);
+        }
+    }
+}
+
+
+
diff --git a/jhMaster/JavaHelp/src/new/javax/help/JHelpGlossaryNavigator.java b/jhMaster/JavaHelp/src/new/javax/help/JHelpGlossaryNavigator.java
new file mode 100644
index 0000000000000000000000000000000000000000..c202926732c612d0cc765725c432578e0c7752f7
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/JHelpGlossaryNavigator.java
@@ -0,0 +1,99 @@
+/*
+ * @(#)JHelpGlossaryNavigator.java	1.2 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help;
+
+import javax.swing.Icon;
+import javax.swing.UIManager;
+import javax.swing.UIDefaults;
+import javax.swing.LookAndFeel;
+import javax.help.*;
+import java.beans.*;
+
+/**
+ * JHelpGlossaryNavigator is a JHelpNavigator for a Glossary
+ *
+ * @author Roger Brinkley
+ * @author Richard Gregor
+ * @version   1.2     10/30/06
+ */
+
+public class JHelpGlossaryNavigator extends JHelpNavigator {
+
+    /**
+     * Creates JHelpGlossaryNavigator from given GlossaryView
+     *
+     * @param info The GlossaryView
+     */
+    public JHelpGlossaryNavigator(NavigatorView info) {
+	super(info);
+    }
+    /**
+     * Creates JHelpGlossaryNavigator from given GlossaryView and HelpModel
+     *
+     * @param info The GlossaryView
+     * @param model The HelpModel
+     */
+    public JHelpGlossaryNavigator(NavigatorView info, HelpModel model) {
+	super(info, model);
+    }
+
+    /**
+     * Creates JHelpGlossaryNavigator from given HelpSet, name and title
+     *
+     * @param hs The HelpSet
+     * @param name The name of GlossaryView
+     * @param title The title
+     */
+
+    public JHelpGlossaryNavigator(HelpSet hs, String name, String title)
+	throws InvalidNavigatorViewException
+    {
+	super(new GlossaryView(hs, name, title, null));
+    }
+
+
+    /**
+     * Returns UIClassID
+     *
+     * @return The ID of UIClass representing JHelpGlossaryNavigator
+     */
+    public String getUIClassID() {
+	return "HelpGlossaryNavigatorUI";
+    }
+
+
+
+    private static final boolean debug = false;
+    private static void debug(Object m1, Object m2, Object m3) {
+	if (debug) {
+	    System.err.println("JHelpGlossaryNavigator: "+m1+m2+m3);
+	}
+    }
+    private static void debug(Object m1) { debug(m1,null,null); }
+    private static void debug(Object m1, Object m2) { debug(m1,m2,null); }
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/JHelpIndexNavigator.java b/jhMaster/JavaHelp/src/new/javax/help/JHelpIndexNavigator.java
new file mode 100644
index 0000000000000000000000000000000000000000..e3b28c33373fe47f4818894fd3bb48522d2d156f
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/JHelpIndexNavigator.java
@@ -0,0 +1,161 @@
+/*
+ * @(#)JHelpIndexNavigator.java	1.40 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help;
+
+import java.net.URL;
+import javax.help.plaf.HelpNavigatorUI;
+
+/**
+ * JHelpIndexNavigator is a JHelpNavigator for an Index.
+ *
+ * All the tree navigation and selection has been delegated to the UI
+ * where the JTree is created.
+ *
+ * @author Roger D. Brinkley
+ * @author Eduardo Pelegri-Llopart
+ * @version	1.40	10/30/06
+ */
+
+public class JHelpIndexNavigator extends JHelpNavigator {
+    /**
+     * Creates an Index navigator.
+     *
+    * @param view The NavigatorView
+     */
+    public JHelpIndexNavigator(NavigatorView view) {
+       super(view, null);
+    }
+
+    /**
+     * Creates a Index navigator.
+     *
+    * @param view The NavigatorView.
+    * @param model The model for the Navigator.
+     */
+    public JHelpIndexNavigator(NavigatorView view, HelpModel model) {
+	super(view, model);
+    }
+  
+
+    
+    // HERE - label & Locale?
+    // HERE - URL data vs Hashtable?
+    /**
+     * Creates an Index navigator with explicit arguments.  Note that this should not throw
+     * an InvalidNavigatorViewException since we are implicitly passing the type.
+     *
+    * @param hs HelpSet
+    * @param name The name identifying this HelpSet.
+    * @param label The label to use (for this locale).
+    * @param data The "data" part of the parameters, a URL location of the TOC data.
+     */
+    public JHelpIndexNavigator(HelpSet hs,
+			       String name, String label, URL data)
+	throws InvalidNavigatorViewException
+    {
+	super(new IndexView(hs, name, label, createParams(data)));
+    }
+
+    /**
+     * Gets the UID for this JComponent.
+     */
+    public String getUIClassID() {
+	return "HelpIndexNavigatorUI";
+    }
+
+    /**
+     * Determines if this instance of a JHelpNavigator can merge its data with another one.
+     *
+     * @param view The data to merge
+     * @return Whether it can be merged
+     *
+     * @see merge(NavigatorView)
+     * @see remove(NavigatorView)
+     */
+    public boolean canMerge(NavigatorView view) {
+	if (view instanceof IndexView &&
+	    getNavigatorName().equals(view.getName())) {
+	    return true;
+	}
+	return false;
+    }
+
+    /**
+     * Merges some NavigatorView into this instance.
+     *
+     * @param view The data to merge
+     * @exception IllegalArgumentException
+     * @exception IllegalStateException
+     *
+     * @see canMerge(NavigatorView)
+     * @see remove(NavigatorView)
+     */
+    public void merge(NavigatorView view) {
+	debug("merge of: "+view);
+	this.getUI().merge(view);
+    }
+
+    /**
+     * Removes a NavigatorView from this instance.
+     *
+     * @param view The data to merge
+     * @exception IllegalArgumentException
+     * @exception IllegalStateException
+     *
+     * @see canMerge(NavigatorView)
+     * @see merge(NavigatorView)
+     */
+    public void remove(NavigatorView view) {
+	this.getUI().remove(view);
+    }
+    
+    /**
+     * Sets state of navigation entry for given target to expanded. Non-empty entry is expanded. Empty entry is visible. 
+     *
+     * @param target The target to expand
+     */
+     public void expandID(String target){
+         firePropertyChange("expand"," ",target);
+    }
+    
+    /**
+     * Sets state of navigation entry for given target to collapsed if entry is visible. Parent is collapsed if entry is empty.
+     * 
+     * @param target The target to collapse
+     */
+    public void collapseID(String target){
+        firePropertyChange("collapse"," ",target);
+    }    
+
+    private static final boolean debug = false;
+    private static void debug(String msg) {
+  	if (debug) {
+  	    System.err.println("JHelpIndexNavigator: "+msg);
+	}
+    }
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/JHelpNavigator.java b/jhMaster/JavaHelp/src/new/javax/help/JHelpNavigator.java
new file mode 100644
index 0000000000000000000000000000000000000000..47a21e8b7d691b61b29898be41c7becce906d130
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/JHelpNavigator.java
@@ -0,0 +1,372 @@
+/*
+ * @(#)JHelpNavigator.java	1.68 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help;
+
+import javax.swing.*;
+import javax.swing.plaf.ComponentUI;
+import javax.accessibility.*;
+import java.net.*;
+import java.util.Vector;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.Hashtable;
+import java.beans.*;
+import javax.help.event.*;
+import javax.help.plaf.HelpNavigatorUI;
+import javax.help.Map.ID;
+
+/**
+ * A JHelpNavigator is a control that presents navigational help data.
+ * It is identified by a type and it interacts with a HelpModel.
+ *
+ * There are three JHelpNavigators that most JavaHelp implementations should
+ * support:
+ *
+ * @see javax.help.JHelpTOCNavigator
+ * @see javax.help.JHelpIndexNavigator
+ * @see javax.help.JHelpSearchNavigator
+ *
+ * This class is intended to be extended. To use this class by itself
+ * requires a platform look and feel (plaf) class that extends 
+ * <tt>javax.help.plaf.HelpNavigatorUI</tt>. Additionally,
+ * the UIDefaults table requires an entry for "HelpViewerUI" that points to
+ * the plaf class.
+ *
+ * @author Roger D. Brinkley
+ * @author Eduardo Pelegri-Llopart
+ * @author Richard Gregor
+ * @version	1.68	10/30/06
+ */
+
+public class JHelpNavigator extends JComponent implements Accessible{
+    protected HelpModel helpModel;
+    protected String type;
+    private static String jhPackageName;
+    private NavigatorView view;
+    private TreeItem[] selectedItems;
+    
+ 
+    /**
+     * Returns a JHelpNavigator with an instance of DefaultHelpModel as its 
+     * data model.
+     *
+     * @param view The NavigatorView to use. If <tt>view</tt> is null it creates a JHelpTOCNavigator
+     * with a null NavigatorView.
+     */
+    public JHelpNavigator(NavigatorView view) {
+	super();
+	this.view = view;
+	if (view != null) {
+	    setModel(new DefaultHelpModel(view.getHelpSet()));
+	} else {
+	    setModel(null);
+	}
+	updateUI();
+    }
+
+    /**
+     * Constructs a JHelpNavigator from some view and with a preexisting model and in default initial state of navigation
+     * entries.
+     *
+     * @param view The NavigatorView. If <tt>view</tt> is null it creates a JHelpNavigator
+     * with a null NavigatorView.
+     * @param model The model that generates changes. 
+     * If <tt>model</tt> is null it creates a JHelpNavigator without a model.
+     */
+    public JHelpNavigator(NavigatorView view, HelpModel model) {
+	super();
+	this.view = view;
+	setModel(model);
+	updateUI();
+        
+    }
+
+    /**
+     * Returns a list of selected items
+     */
+    public TreeItem[] getSelectedItems() {
+	if(selectedItems == null) {
+	    return new TreeItem[0];
+	} else {
+	    return (TreeItem[]) selectedItems.clone();
+	}
+    }
+
+    /**
+     * Sets the list of selected items
+     */
+    public void setSelectedItems(TreeItem[] selectedItems) {
+	TreeItem[] oldValue = this.selectedItems;
+	this.selectedItems = selectedItems;
+	firePropertyChange("SelectedItemsChangedProperty", oldValue, this.selectedItems);
+    }
+
+    /**
+     * @return "HelpNavigatorUI"
+     */
+    public String getUIClassID()
+    {
+        return "HelpNavigatorUI";
+    }
+
+    /**
+     * Determines if this instance of a JHelpNavigator can merge its data with another one.
+     *
+     * @param view The data to merge.
+     * @return Whether it can be merged.
+     *
+     * @see merge(NavigatorView)
+     * @see remove(NavigatorView)
+     */
+    public boolean canMerge(NavigatorView view) {
+	return false;
+    }
+
+    /**
+     * Merged a NavigatorView into this instance.
+     *
+     * @param view The data to merge
+     * @exception UnsupportedOperationException
+     *
+     * @see canMerge(NavigatorView)
+     * @see remove(NavigatorView)
+     */
+    public void merge(NavigatorView view) {
+	throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Removes a NavigatorView from this instance.
+     *
+     * @param view The data to merge
+     * @exception UnsupportedOperationException
+     *
+     * @see canMerge(NavigatorView)
+     * @see merge(NavigatorView)
+     */
+    public void remove(NavigatorView view) {
+	throw new UnsupportedOperationException();
+    }
+
+    // ========= Navigator Identification ========
+
+    /**
+     * Names this Navigator.
+     *
+     * @return The name of this Navigator.  This is locale independent and can be
+     * 	used by the application to identify the view.
+     */
+    public String getNavigatorName() {
+	return view.getName();
+    }
+
+    /**
+     * Gets the NavigatorView that created this Navigator View.
+     *
+     * @return the NavigatorView
+     */
+    public NavigatorView getNavigatorView() {
+	return view;
+    }
+
+    // HERE -- Do we want these, or just the getNavigatorView()? - epll
+
+    /**
+     * Gets the name of this navigator view.
+     *
+     * @return The label for this NavigatorView.
+     */
+    public String getNavigatorLabel() {
+	return view.getLabel();
+    }
+
+    /**
+     * Gets locale-dependent name for this navigator view.
+     *
+     * @return the label for this NavigatorView. If locale is null it is 
+     * treated as the default Locale.
+     */
+    public String getNavigatorLabel(Locale locale) {
+	return view.getLabel(locale);
+    }
+
+    /**
+     * Gets an icon to identify this Navigator.  Currently this is a read-only
+     * property.
+     *
+     * @return An icon to identify this navigator.
+     */
+    public Icon getIcon() {
+	return getUI().getIcon();
+    }
+
+
+    // =========== Model and UI methods ===========
+
+    /**
+     * Sets the HelpModel that provides the data.
+     * @param newModel The HelpModel for this component. A null for newModel
+     * is valid.
+     */
+    public void setModel(HelpModel newModel) {
+	HelpModel oldModel = helpModel;
+        if (newModel != oldModel) {
+            helpModel = newModel;
+            firePropertyChange("helpModel", oldModel, helpModel);
+            invalidate();
+        }
+    }
+
+    /**
+     * Returns the HelpModel that provides the data.
+     */
+    public HelpModel getModel() {
+	return helpModel;
+    }
+
+    /**
+     * Sets the HelpUI that provides the current look and feel.
+     */
+    public void setUI(HelpNavigatorUI ui) {
+	if ((HelpNavigatorUI)this.ui != ui) {
+	    super.setUI(ui);
+	}
+    }
+
+    /**
+     * Returns the HelpUI that provides the current look and feel.
+     */
+    public HelpNavigatorUI getUI() {
+	return (HelpNavigatorUI)ui;
+    }
+
+    /**
+     * Replaces the UI with the latest version from the default 
+     * UIFactory.
+     *
+     * @overrides updateUI in class JComponent
+     */
+    public void updateUI() {
+        SwingHelpUtilities.installUIDefaults();
+	setUI((HelpNavigatorUI)UIManager.getUI(this));
+        invalidate();
+    }
+
+    /*
+     * Makes sure the Look and Feel will be set for the Help Component.
+     */
+    static {
+	SwingHelpUtilities.installLookAndFeelDefaults();
+    }
+
+    // Be a source for HelpModelEvents
+
+    /**
+     * Adds a listener for the HelpModelEvent posted after the model has
+     * changed.
+     * 
+     * @param l - The listener to add.
+     * @see javax.help.HelpModel#removeHelpModelListener
+     */
+    public void addHelpModelListener(HelpModelListener l) {
+	getModel().addHelpModelListener(l);
+    }
+
+    /**
+     * Removes a listener previously added with <tt>addHelpModelListener</tt>.
+     *
+     * @param l - The listener to remove.
+     * @see javax.help.HelpModel#addHelpModelListener
+     */
+    public void removeHelpModelListener(HelpModelListener l) {
+	getModel().removeHelpModelListener(l);
+    }
+
+    /**
+     * Creates the parameters for a Navigator from data stored in a URL.
+     *
+     * @return A Hashtable of parameters
+     */
+
+    protected static Hashtable createParams(URL data) {
+	Hashtable back = new Hashtable();
+	back.put("data", data.toString());
+	return back;
+    }
+
+
+    
+    /**
+     * For printf debugging.
+     */
+    private static final boolean debug = false;
+    private static void debug(String str) {
+        if (debug) {
+            System.err.println("JHelpNavigator: " + str);
+        }
+    }
+
+/////////////////
+// Accessibility support
+////////////////
+
+    /**
+     * Get the AccessibleContext associated with this JComponent.
+     *
+     * @return The AccessibleContext of this JComponent
+     */
+    public AccessibleContext getAccessibleContext() {
+        if (accessibleContext == null) {
+            accessibleContext = new AccessibleJHelpNavigator();
+        }
+        return accessibleContext;
+    }
+
+    /**
+     * The class used to obtain the accessible role for this object.
+     * <p>
+     * <strong>Warning:</strong>
+     * Serialized objects of this class will not be compatible with
+     * future Swing releases.  The current serialization support is appropriate
+     * for short term storage or RMI between applications running the same
+     * version of Swing.  A future release of Swing will provide support for
+     * long term persistence.
+     */
+    protected class AccessibleJHelpNavigator extends AccessibleJComponent {
+
+        /**
+         * Get the role of this object.
+         *
+         * @return An instance of AccessibleRole describing the role of the
+         * object
+         */
+        public AccessibleRole getAccessibleRole() {
+            return AccessibleRole.PANEL;
+        }
+    }
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/JHelpSearchNavigator.java b/jhMaster/JavaHelp/src/new/javax/help/JHelpSearchNavigator.java
new file mode 100644
index 0000000000000000000000000000000000000000..ccebc85bbf42a761d06dc9daef870af401f9f639
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/JHelpSearchNavigator.java
@@ -0,0 +1,204 @@
+/*
+ * @(#)JHelpSearchNavigator.java	1.52 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help;
+
+import java.net.URL;
+import javax.help.search.SearchEngine;
+import javax.help.search.MergingSearchEngine;
+
+/**
+ * A JHelpNavigator for search data.
+ * All of the tree navigation and selection has been delegated to the UI.
+ *
+ * @author Roger D. Brinkley
+ * @author Eduardo Pelegri-Llopart
+ * @version	1.52	10/30/06
+ */
+
+public class JHelpSearchNavigator extends JHelpNavigator {
+    private MergingSearchEngine search;	// our search engine
+
+
+    /**
+     * Creates a Search navigator
+     *
+     * @param view The NavigatorView. If view is null it creates a JHelpSearchNavigator
+     * with a null NavigatorView.
+     */
+    public JHelpSearchNavigator(NavigatorView view) {
+	super(view, null);
+    }
+
+    /**
+     * Creates a Search navigator.
+     *
+     * @param view The NavigatorView. If <tt>view</tt> is null it creates a JHelpSearchNavigator
+     * with a null NavigatorView.
+     * @param model The HelpModel this Navigator is presenting. If <tt>model</tt> is null it 
+     * creates a JHelpSearchNavigator witout a model.
+     */
+    public JHelpSearchNavigator(NavigatorView view, HelpModel model) {
+	super(view, model);
+    }
+    
+
+
+    // HERE - label & Locale?
+    /**
+    * Creates a TOC navigator with explicit arguments.  Note that this should not throw
+    * an InvalidNavigatorViewException since the type is passed implicitly.
+    *
+    * @param hs HelpSet
+    * @param name The name indentifying this HelpSet.
+    * @param label The label to use (for this locale).
+    * @param data The "data" part of the parameters, a URL to the location of the TOC data.
+    */
+    public JHelpSearchNavigator(HelpSet hs,
+				String name, String label, URL data) 
+	throws InvalidNavigatorViewException
+    {
+	super(new SearchView(hs, name, label, createParams(data)));
+    }
+
+
+    /**
+     * The UID for this JComponent.
+     */
+    public String getUIClassID() {
+	return "HelpSearchNavigatorUI";
+    }
+
+    /**
+     * Search Database methods.
+     */
+
+    /**
+     * Instantiates and returns a SearchEngine class. 
+     * The default query engine to use is <tt>com.sun.java.help.search.SearchEngine</tt>,
+     * but this can be changed through the &lt;engine&gt;&lt;/engine&gt; attribute
+     * of the view.
+     *
+     * @return The SearchEngine instantiation.
+     */
+    public SearchEngine getSearchEngine() {
+	if (search == null) {
+	    search = new MergingSearchEngine(getNavigatorView());
+	}
+	return search;
+    }
+
+    /**
+     * Explicitly changes the default (overriding what is in the HelpSet).
+     *
+     * @param search A SearchEngine instantiation.
+     */
+    public void setSearchEngine(SearchEngine search) {
+	this.search = new MergingSearchEngine(search);
+    }
+
+    /**
+     * Default for the search engine.
+     */
+
+    protected String getDefaultQueryEngine() {
+	return HelpUtilities.getDefaultQueryEngine();
+    }
+
+    /**
+     * Determines if this instance of a JHelpNavigator can merge its data with another one.
+     *
+     * @param view The data to merge.
+     * @return Whether it can be merged.
+     *
+     * @see merge(NavigatorView)
+     * @see remove(NavigatorView)
+     */
+    public boolean canMerge(NavigatorView view) {
+	if (view instanceof SearchView &&
+	    getNavigatorName().equals(view.getName())) {
+	    debug("canMerge: true");
+	    return true;
+	}
+	debug("canMerge: false");
+	return false;
+    }
+
+    /**
+     * Merges a NavigatorView into this instance.
+     *
+     * @param view The data to merge.
+     * @exception IllegalArgumentException
+     * @exception IllegalStateException
+     *
+     * @see canMerge(NavigatorView)
+     * @see remove(NavigatorView)
+     */
+    public void merge(NavigatorView view) {
+	// Add the requested query engine to our list of engines
+	debug("JHelpSearchNavigator.merge invoked");
+	debug("  params: "+view.getParameters());
+	if (search == null) {
+	    search = (MergingSearchEngine) getSearchEngine();
+	}
+	search.merge(view);
+	debug("merge: "+view);
+	this.getUI().merge(view);
+    }
+
+    /**
+     * Removes a NavigatorView from this instance.
+     *
+     * @param view The data to merge.
+     * @exception IllegalArgumentException
+     * @exception IllegalStateException
+     *
+     * @see canMerge(NavigatorView)
+     * @see merge(NavigatorView)
+     */
+    public void remove(NavigatorView view) {
+	// Remove the requested query engine from our list of engines
+	debug("JHelpSearchNavigator.remove invoked");
+	debug("  params: "+view.getParameters());
+	if (search == null) {
+	    search = (MergingSearchEngine) getSearchEngine();
+	}
+	search.remove(view);
+	debug("remove: "+view);
+	this.getUI().remove(view);
+    }
+
+    private static final boolean debug = false;
+    private static void debug(String msg) {
+	if (debug) {
+	    System.err.println("JHelpSearchNavigator: "+msg);
+	}
+    }
+
+
+}
+
diff --git a/jhMaster/JavaHelp/src/new/javax/help/JHelpTOCNavigator.java b/jhMaster/JavaHelp/src/new/javax/help/JHelpTOCNavigator.java
new file mode 100644
index 0000000000000000000000000000000000000000..1103c7e82ea253452447bde380bbf4f7417c79ba
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/JHelpTOCNavigator.java
@@ -0,0 +1,172 @@
+/*
+ * @(#)JHelpTOCNavigator.java	1.44 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help;
+
+import java.net.URL;
+import java.util.Vector;
+import java.util.Enumeration;
+
+
+/**
+ * A JHelpNavigator for a TOC.
+ *
+ * All of the tree navigation and selection has been delegated to the UI
+ * where the JTree is created.
+ *
+ * @author Roger D. Brinkley
+ * @author Eduardo Pelegri-Llopart
+ * @version	1.44	10/30/06
+ */
+
+public class JHelpTOCNavigator extends JHelpNavigator {
+ 
+    /**
+     * Create a TOC navigator
+     *
+     * @param view The NavigatorView. If view is null it creates a JHelpTOCNavigator
+     * without a HelpModel and a null NavigatorView.
+     */
+    public JHelpTOCNavigator(NavigatorView view) {
+	super(view, null);
+    }
+
+    /**
+     * Creates a TOC navigator.
+     *
+     * @param view The NavigatorView. If <tt>view</tt> is null it creates a JHelpTOCNavigator
+     * with a null NavigatorView.
+     * @param model The model for the Navigator. If <tt>model</tt> is null it creates a
+     * JHelpTOCNavigator witout a model.
+     */
+
+    public JHelpTOCNavigator(NavigatorView view, HelpModel model) {
+	super(view, model);
+    }
+
+
+
+    /**
+     * Creates a TOC navigator with explicit arguments.  Note that this should not throw
+     * an InvalidNavigatorViewException since the type is implicitly passed.
+     *
+    * @param hs HelpSet
+    * @param name The name indentifying this HelpSet.
+    * @param label The label to use (for this locale).
+    * @param data The "data" part of the parameters, a URL location of the TOC data.
+     */
+    public JHelpTOCNavigator(HelpSet hs,
+			     String name, String label, URL data) 
+	throws InvalidNavigatorViewException
+    {
+	super(new TOCView(hs, name, label, createParams(data)));
+    }
+
+
+    /**
+     * The UID for this JComponent.
+     */
+    public String getUIClassID() {
+	return "HelpTOCNavigatorUI";
+    }
+
+    /**
+     * Determines if this instance of a JHelpNavigator can merge its data with another one.
+     *
+     * @param view The data to merge.
+     * @return Whether it can be merged.
+     * @see merge()
+     * @see remove()
+     */
+    public boolean canMerge(NavigatorView view) {
+	if (view instanceof TOCView &&
+	    getNavigatorName().equals(view.getName())) {
+	    debug("canMerge: true");
+	    return true;
+	}
+	debug("canMerge: false");
+	return false;
+    }
+
+    /**
+     * Merges a NavigatorView into this instance.
+     *
+     * @param view The data to merge.  This must be a TOCView.
+     * @see canMerge()
+     * @see remove()
+     * @exception IllegalArgumentException
+     * @exception IllegalStateException
+     */
+    public void merge(NavigatorView view) {
+	debug("merge: "+view);
+	this.getUI().merge(view);
+    }
+
+    /**
+     * Removes a NavigatorView from this instance.
+     *
+     * @param view The data to merge.
+     * @see canMerge()
+     * @see merge()
+     * @exception IllegalArgumentException
+     * @exception IllegalStateException
+     */
+    public void remove(NavigatorView view) {
+	// this should recompute the view
+	this.getUI().remove(view);
+    }
+
+    /**
+     * Sets state of navigation entry for given target to expanded. Non-empty entry is expanded. Empty entry is visible. 
+     *
+     * @param target The target to expand
+     */
+     public void expandID(String target){
+         firePropertyChange("expand"," ",target);
+    }
+    
+    
+    /**
+     * Sets state of navigation entry for given target to collapsed if entry is visible. Parent is collapsed if entry is empty.
+     * 
+     * @param target The target to collapse
+     */
+    public void collapseID(String target){
+        firePropertyChange("collapse"," ",target);
+    }
+    
+    
+    private static final boolean debug = false;
+    private static void debug(String msg) {
+	if (debug) {
+	    System.err.println("JHelpTOCNavigator: "+msg);
+	}
+    }
+
+
+}
+
diff --git a/jhMaster/JavaHelp/src/new/javax/help/MainWindow.java b/jhMaster/JavaHelp/src/new/javax/help/MainWindow.java
new file mode 100644
index 0000000000000000000000000000000000000000..a2edfc29659ceeb71c9c090c8f5c1d3165fd880e
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/MainWindow.java
@@ -0,0 +1,99 @@
+/*
+ * @(#)MainWindow.java	1.3 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help;
+
+
+/**
+ * MainWindow is a class that will create a single main help 
+ * window for an application. Although there is generally only one per
+ * application there can  be multiple MainWindow.
+ * By default it is a tri-paned fully decorated window
+ * consisting of a toolbar, navigator pane, and help content view. By default
+ * the class is not destroyed when the window exits.
+ *
+ * @author Roger D.Brinkley
+ * @version	1.3	10/30/06
+ * @since 2.0
+ *
+ * @see javax.help.WindowPresentation
+ * @see javax.help.Presentation
+ */
+
+public class MainWindow extends WindowPresentation {
+
+    private MainWindow(HelpSet hs) {
+	super(hs);
+    }
+
+    /**
+     * Creates a new MainWindow for a given HelpSet and 
+     * HelpSet.Presentation "name". If the "name"d HelpSet.Presentation
+     * does not exist in HelpSet then the default HelpSet.Presentation
+     * is used.
+     * 
+     * @param hs The HelpSet used in this presentation
+     * @param name The name of the Presentation to create - also the name
+     *             of the HelpSet.Presentation to use.
+     * @returns Presentation A unique MainWindow. 
+     */
+    static public Presentation getPresentation(HelpSet hs, String name) {
+	MainWindow mwp = new MainWindow(hs);
+	if (hs != null) {
+	    HelpSet.Presentation presentation = null;
+
+	    // get a named presentation if one exists
+	    if (name != null) {
+		presentation = hs.getPresentation(name);
+	    }
+
+	    // get the default presentation if one exits
+	    if (presentation == null) {
+		presentation = hs.getDefaultPresentation();
+	    }
+
+	    // set the presentation
+	    // a null is ok here as it will just return.
+	    mwp.setHelpSetPresentation(presentation);
+	}
+	return mwp;
+    }
+
+    /**
+     * Debugging code...
+     */
+
+    private static final boolean debug = false;
+    private static void debug(Object msg) {
+	if (debug) {
+	    System.err.println("MainWindow: "+msg);
+	}
+    }
+ 
+}
+
+
diff --git a/jhMaster/JavaHelp/src/new/javax/help/Map.java b/jhMaster/JavaHelp/src/new/javax/help/Map.java
new file mode 100644
index 0000000000000000000000000000000000000000..3bd3e954cd65701a0a1232efa22e04e2c2694280
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/Map.java
@@ -0,0 +1,200 @@
+/*
+ * @(#)Map.java	1.13 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help;
+
+import java.net.URL;
+import java.net.MalformedURLException;
+import java.util.*;
+import java.io.Serializable;
+
+/**
+ * A Map is the interface to ID<->URL mapping.
+ *
+ * @author Eduardo Pelegri-Llopart
+ * @author Stepan Marek
+ * @version	1.13	10/30/06
+ */
+public interface Map {
+    /**
+     * Determines if the ID is valid (defined in the map file).
+     * 
+     * @param id The String ID.
+     * @param hs The HelpSet against which to resolve the string.
+     * @return True if the ID is valid, false if not valid.
+     */
+
+    public boolean isValidID(String id, HelpSet hs);
+
+    /**
+     * Gets an enumeration of all the IDs in a Map.
+     *
+     * @return An enumeration of all the IDs in a Map.
+     */
+    // We need this so we can add FlatMaps to TryMaps - epll
+    public Enumeration getAllIDs();
+
+    /**
+     * Gets the URL that corresponds to a given ID in the Map.
+     *
+     * @param id The ID to get the URL for.
+     * @return URL The matching URL.  Null if this map cannot solve the ID.
+     * @exception MalformedURLException if the URL is malformed
+     */
+    public URL getURLFromID(ID id) throws MalformedURLException;
+
+    /**
+     * Determines if the URL corresponds to an ID in the Map.
+     *
+     * @param url The URL to check on.
+     * @return True if this is an ID, false otherwise.
+     */
+    public boolean isID(URL url);
+
+    /**
+     * Determines the ID for this URL.
+     * 
+     * @param url The URL to get the ID for.
+     * @return The ID (or null if URL does not correspond to an ID).
+     */
+    public ID getIDFromURL(URL url);
+
+    // HERE - do we want this.  It is *very* expensive to do  - epll
+
+    /**
+     * Determines the ID that is "closest" to this URL (with a given anchor).
+     *
+     * The definition of this is up to the implementation of Map.  In particular,
+     * it may be the same as getIDFromURL().
+     *
+     * @param url A URL
+     * @return The closest ID in this map to the given URL.
+     */
+    public ID getClosestID(URL url);
+
+    /**
+     * Determines the IDs related to this URL.
+     *
+     * @param URL The URL to which to compare the Map IDs.
+     * @return Enumeration of Map.Key (Strings/HelpSet)
+     */
+    public Enumeration getIDs(URL url);
+
+    /**
+     * An ID is a pair of String, HelpSet.
+     *
+     * An ID fully identifies a "location" within a HelpSet.
+     */
+    
+    final public class ID implements Serializable{
+	public String id;
+	public HelpSet hs;
+	
+	/**
+	 * A location within a HelpSet.  If id or hs are null, a null ID is returned.
+	 *
+	 * @param id The String
+	 * @param hs The HelpSet
+	 * @exception BadIDException if String is not within the Map of the
+	 * HelpSet.
+	 */
+
+	public static ID create(String id, HelpSet hs) throws BadIDException {
+	    if (hs == null ||
+		id == null) {
+		return null;
+	    }
+
+	    Map map = hs.getCombinedMap();
+	    if (! map.isValidID(id, hs)) {
+		throw new BadIDException("Not valid ID: "+id, map, id, hs);
+	    }
+	    return new ID(id, hs);
+	}
+
+	/**
+	 * Creates an ID object.
+	 */
+
+	private ID(String id, HelpSet hs) throws BadIDException {
+	    this.id = id;
+	    this.hs = hs;
+	}
+
+        /** Getter for property hs.
+         * @return Value of property hs.
+         */
+        public HelpSet getHelpSet() {
+            return hs;
+        }
+
+        /** Getter for property id.
+         * @return Value of property id.
+         */
+        public String getIDString() {
+            return id;
+        }
+            
+        /**
+         * Returns the URL that the Map.ID refers to.
+         *
+         * @return URL The matching URL. Null if the map cannot solve the ID.
+         * @exception MalformedURLException if the URL is malformed
+         * @see javax.help.Map#getURLFromID(javax.help.Map.ID id)
+         */
+        public URL getURL() throws MalformedURLException {
+            if (hs == null || id == null) {
+                return null;
+            }
+            try {
+                return hs.getCombinedMap().getURLFromID(this);
+            } catch (MalformedURLException e) {
+                throw e;
+            }
+        }
+        
+	/**
+	 * Determines if two IDs are equal.
+	 * @param o The object to compare.
+	 */
+
+	public boolean equals(Object o) {
+	    if (o instanceof ID) {
+		ID id2 = (ID) o;
+		return (id2.id.equals(id) && (id2.hs.equals(hs)));
+	    }
+	    return false;
+	}
+
+	/**
+	 * Gets an external represenation of an ID.
+	 */
+	public String toString() {
+	    return("ID: "+id+", "+hs);
+	}
+    }
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/Merge.java b/jhMaster/JavaHelp/src/new/javax/help/Merge.java
new file mode 100644
index 0000000000000000000000000000000000000000..c2a40c05686c02875107cff47f66879b2a8a063d
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/Merge.java
@@ -0,0 +1,158 @@
+/*
+ * @(#)Merge.java	1.6 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help;
+
+import java.util.Locale;
+import javax.swing.tree.TreeNode;
+import javax.swing.tree.DefaultMutableTreeNode;
+import java.lang.reflect.Constructor;
+
+/**
+ * Common superclass for all merge types
+ *
+ * @author  Richard Gregor
+ * @version	1.6	10/30/06 
+ */
+public abstract class Merge {
+
+    /**
+     * Slave node
+     */
+    protected DefaultMutableTreeNode slaveTopNode;
+
+    /**
+     * HelpSet's locale which is used in sorting
+     */
+    protected Locale locale;
+    
+    /**
+     * Constructs Merge for master and slave NavigatorViews
+     *
+     * @param master The master NavigatorView
+     * @param slave The slave NavigatorView
+     */
+    protected Merge(NavigatorView master, NavigatorView slave){
+        
+        try {
+            Class clss = Class.forName("javax.help.TOCView");
+            if (clss.isInstance(slave)) {
+                this.slaveTopNode = ((TOCView)slave).getDataAsTree();
+	    }
+            clss = Class.forName("javax.help.IndexView");
+            if (clss.isInstance(slave)) {
+                this.slaveTopNode = ((IndexView)slave).getDataAsTree();
+	    }
+        } catch(ClassNotFoundException exp) {
+            System.err.println(exp);
+        }
+                       
+        locale = master.getHelpSet().getLocale();
+        if(locale == null)
+            locale = Locale.getDefault();
+    }
+    
+    /**
+     * Processes merge. Changes master node according merge rules using slave node.
+     *
+     * @param node The master node 
+     * @return The changed master node
+     */
+    public abstract TreeNode processMerge(TreeNode node);
+
+    /**
+     * Merge Nodes. Merge two nodes according to the merging rules of the
+     * masterNode. Each Subclass should override this implementation.
+     *
+     * @param master The master node to merge with 
+     * @param slave The node to merge into the master
+     */
+    public static void mergeNodes(TreeNode master, TreeNode slave) {
+	// Doesn't do anything
+    }
+
+    /**
+     * Merge Node Children. Merge the children of a node according to the
+     * merging rules of the parent. Each subclass must implement this method
+     *
+     * @param node The parent node from which the children are merged
+     */
+    public static void mergeNodeChildren(TreeNode node) {
+	// Doesn't do anything
+    }
+    
+    /**
+     * Default Merge factory which creates concrete Merge objects
+     */ 
+    public static class DefaultMergeFactory {
+
+        /**
+         * Returns suitable Merge object
+         *
+         * @param masterView The master NavigatorView
+         * @param slaveView The slave NavigatorView
+         * @return The Merge object
+         */
+        public static Merge getMerge(NavigatorView masterView, NavigatorView slaveView) {
+            
+            Merge mergeObject = null;
+	    // throw an NPE early
+	    if (masterView == null || slaveView == null) {
+		throw new NullPointerException("masterView and/or slaveView are null");
+
+	    }
+            String mergeType = masterView.getMergeType();
+	    HelpSet hs = masterView.getHelpSet();
+            Locale locale = hs.getLocale();
+	    ClassLoader loader = hs.getLoader();
+	    Class klass;
+	    Constructor konstructor;
+            
+	    if (mergeType != null) {
+		try {
+		    Class types[] = { NavigatorView.class, 
+				      NavigatorView.class };
+		    Object args[] = { masterView, slaveView };
+		    if (loader == null) {
+			klass = Class.forName(mergeType);
+		    } else {
+			klass = loader.loadClass(mergeType);
+		    }
+		    konstructor = klass.getConstructor(types);
+		    mergeObject = (Merge) konstructor.newInstance(args);
+		} catch (Exception ex) {
+		    ex.printStackTrace();
+		    throw new RuntimeException("Could not create Merge type " +
+					       mergeType);
+		}
+	    } else {
+		mergeObject = new AppendMerge(masterView, slaveView);
+	    }
+            return mergeObject;
+        }
+    }
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/MergeHelpUtilities.java b/jhMaster/JavaHelp/src/new/javax/help/MergeHelpUtilities.java
new file mode 100644
index 0000000000000000000000000000000000000000..9729e50a76d39f35dc002b6ce2dc7c51f3a898d9
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/MergeHelpUtilities.java
@@ -0,0 +1,291 @@
+/*
+ * @(#)MergeHelpUtilities.java	1.9 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help;
+
+import javax.swing.tree.*;
+import java.util.*;
+import java.text.*;
+import java.lang.reflect.Method;
+
+/**
+ * Common utilities for merge types
+ *
+ * @author  Richard Gregor
+ * @version	1.9	10/30/06
+ */
+
+public class MergeHelpUtilities extends Object {
+
+
+    /**
+     * Merge the nodes according the merging rules of the masterNode's
+     * merge type
+     * 
+     * @param masterMergeType The fallback mergeType if masterNode does not have a mergeType
+     * @param masterNode The master node to merge into
+     * @param slaveNode A secondary node that will merge into the master node
+     */
+    public static void mergeNodes(String masterMergeType,
+				  DefaultMutableTreeNode masterNode,
+				  DefaultMutableTreeNode slaveNode) {
+	if (slaveNode.isLeaf()) {
+	    return;
+	}
+	String mergeType = getMergeType(masterNode);
+	if (mergeType == null) {
+	    mergeType = masterMergeType;
+	}
+
+	Class klass;
+	Class types[] =  { TreeNode.class, 
+			   TreeNode.class };
+	Method m;
+	Object args[] = { masterNode, slaveNode };
+	try {
+	    klass = Class.forName(mergeType);
+	    m = klass.getDeclaredMethod("mergeNodes", types);
+	    m.invoke(null, args);
+	} catch (Exception ex) {
+	    ex.printStackTrace();
+	    throw new RuntimeException
+		("Could not find or execute mergeNodes for " +
+		 mergeType);
+	}
+    }
+
+    /**
+     * Merge a nodes children according the merging rules of the node's
+     * merge type
+     *
+     * @param masterMergeType The fallback mergeType if masterNode does not have a mergeType
+     * @param node The node
+     */
+    public static void mergeNodeChildren(String masterMergeType, DefaultMutableTreeNode node) {
+	if (node.isLeaf()) {
+	    return;
+	}
+	String mergeType = getMergeType(node);
+	if (mergeType == null) {
+	    mergeType = masterMergeType;
+	}
+	Class klass;
+	Class types[] =  { TreeNode.class };
+	Method m;
+	Object args[] = { node };
+	try {
+	    klass = Class.forName(mergeType);
+	    m = klass.getDeclaredMethod("mergeNodeChildren", types);
+	    m.invoke(null, args);
+	} catch (Exception ex) {
+	    ex.printStackTrace();
+	    throw new RuntimeException
+		("Could not find or execute mergeNodeChildren for " +
+		 mergeType);
+	}
+    }
+
+    /**
+     * Returns node's merge type
+     *
+     * @param node The node
+     * @return The node's merge type
+     */
+    private static String getMergeType(DefaultMutableTreeNode node) { 
+        TreeItem item = (TreeItem)node.getUserObject();
+        if (item == null) {
+            return null;
+        } else {
+            return item.getMergeType();
+	}
+    }
+    
+    /**
+     * Returns name of node
+     *
+     * @param node The node
+     * @return The name of node 
+     */
+    public static String getNodeName(DefaultMutableTreeNode node) {
+	if (node == null) {
+	    return null;
+	}
+        TreeItem item = (TreeItem)node.getUserObject();
+	if (item == null) {
+	    return null;
+	}
+        return item.getName();
+    }
+    
+    /**
+     * Returns node with given name
+     *
+     * @param parent The parent node 
+     * @param name The name of child
+     * @return The child with given name
+     */
+    public static DefaultMutableTreeNode getChildWithName(DefaultMutableTreeNode parent,String name) {
+        DefaultMutableTreeNode childAtI = null;
+        DefaultMutableTreeNode result = null;
+        
+        for (int i = 0; i < parent.getChildCount(); i++) {
+            childAtI = (DefaultMutableTreeNode)parent.getChildAt(i);
+            if (getNodeName(childAtI).equals(name)) {
+                result = childAtI;
+                break;
+            }
+        }
+        return result;
+        
+    }
+    
+    /**
+     * Returns locale of node
+     *
+     * @param node The node
+     * @return The locale object
+     */    
+    public static Locale getLocale(DefaultMutableTreeNode node) {
+	Locale locale = null;
+        TreeItem item = (TreeItem)node.getUserObject();
+        if (item != null) {
+            locale = item.getLocale();
+	} 
+	if (locale == null) {
+            locale = Locale.getDefault();
+	}
+	return locale;
+    }
+    
+    /**
+     * Compares name of nodes
+     *
+     * @param master The master node
+     * @param slave The slave node
+     * @return negative is master is lexically lower than slave;
+     * positive if master is lexically higher than slave and zero if lexically
+     * identical.
+     */
+    public static int compareNames(DefaultMutableTreeNode master, DefaultMutableTreeNode slave) {
+
+        TreeItem masterItem = (TreeItem)master.getUserObject();
+        debug("haveEqualName - master:"+masterItem);
+        TreeItem slaveItem = (TreeItem)slave.getUserObject();
+        debug("haveEqualName - slave:"+slaveItem);
+        
+	String masterName = masterItem.getName();
+        if (masterName == null) {
+            masterName = " ";
+	}
+
+	String slaveName = slaveItem.getName();
+        if (slaveName == null) {
+            slaveName = " ";
+	}
+
+	Collator collator = Collator.getInstance(getLocale(master));
+        return collator.compare(masterName, slaveName);
+    }
+        
+    /**
+     * Method for comparing ID of nodes
+     *
+     * @param master The master node
+     * @param slave The slave node
+     * @return True if ID is the same
+     */
+    public static boolean haveEqualID(DefaultMutableTreeNode master, DefaultMutableTreeNode slave) {
+        TreeItem masterItem = (TreeItem)master.getUserObject();
+        TreeItem slaveItem = (TreeItem)slave.getUserObject();
+        
+        if (masterItem.getID() == null) {
+            if (slaveItem.getID() == null) {
+                return true;
+            } else {
+                return false;
+	    }
+        } else {
+            if (slaveItem.getID() == null) {
+                return false;
+	    }
+	}
+        
+        //items are not null
+        
+        Map.ID masterMapID = masterItem.getID();
+        Map.ID slaveMapID = slaveItem.getID();
+        
+        if (masterMapID.id == null) {
+            if (slaveMapID.id == null) {
+                return true;
+            } else {
+                return false;
+	    }
+        } else {
+            if (slaveMapID.id == null) {
+                return false;
+	    }
+	}
+        
+        return masterMapID.id.equals(slaveMapID.id);
+    }
+    
+        
+    /**
+     * Marks nodes with the same name but diferent IDs with their HelpSet title
+     *
+     * @param master The master node to mark
+     * @param slave The slave node to mark
+     */
+    
+    public static void markNodes(DefaultMutableTreeNode master, DefaultMutableTreeNode slave) {
+        debug("MarkNodes");
+        TreeItem masterItem = (TreeItem)master.getUserObject();
+        TreeItem slaveItem = (TreeItem)slave.getUserObject();
+        HelpSet masterHS = masterItem.getHelpSet();
+        HelpSet slaveHS = slaveItem.getHelpSet();
+
+	if (masterItem.getName() != null) {
+	    masterItem.setName(masterItem.getName()+"("+masterHS.getTitle()+")");
+	} else { 
+	    masterItem.setName(masterItem.getName()+"("+masterHS.getTitle()+")");
+	}
+	if (slaveItem.getName() != null) {
+	    slaveItem.setName(slaveItem.getName()+"("+slaveHS.getTitle()+")");
+	} else {
+	    slaveItem.setName(slaveItem.getName()+"("+slaveHS.getTitle()+")");
+	}
+    }
+
+    private static boolean debug = false;
+    private static void debug(String msg) {
+        if (debug) {
+            System.out.println("MergeHelpUtilities :"+msg);
+	}
+    }
+}
+
diff --git a/jhMaster/JavaHelp/src/new/javax/help/NavigatorView.java b/jhMaster/JavaHelp/src/new/javax/help/NavigatorView.java
new file mode 100644
index 0000000000000000000000000000000000000000..39d8b33cfbd86862dfb262f26b6df93e369e8675
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/NavigatorView.java
@@ -0,0 +1,219 @@
+/*
+ * @(#)NavigatorView.java	1.28 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help;
+
+import java.util.Locale;
+import java.util.Hashtable;
+import java.awt.Component;
+import java.lang.reflect.*;
+import java.io.Serializable;
+
+/**
+ * Navigational View information
+ *
+ * @author Eduardo Pelegri-Llopart
+ * @author Stepan Marek
+ * @version	1.28	10/30/06
+ */
+
+public abstract class NavigatorView implements Serializable{
+    private HelpSet hs;
+
+    private String name;
+    private String label;
+    private Locale locale;
+    private Hashtable params;
+    private Map.ID imageID;
+    private String mergeType;
+
+    /**
+     * Constructs a Navigator with some given data.  This is protected
+     * so subclasses can use it.
+     *
+     * @param hs The HelpSet that provides context information.
+     * @param name The name of the View.
+     * @param label The label (to show the user) of the View.
+     * @param locale The default locale to interpret the data in this View.
+     * @param params A hashtable that provides different key/values for this type.
+     */
+
+    protected NavigatorView(HelpSet hs,
+			    String name,
+			    String label,
+			    Locale locale,
+			    Hashtable params) 
+    {
+	if (name == null || label == null) {
+	    throw new NullPointerException("Invalid name or label");
+	}
+        this.imageID = null;
+        if (params != null) {
+            String imageID = (String)params.get("imageID");
+            if (imageID != null)
+                this.imageID = Map.ID.create(imageID, hs);
+            this.mergeType = (String)params.get("mergetype");
+        }
+        this.hs = hs;
+	this.name = name;
+	this.label = label;
+	this.locale = locale;
+	this.params = params;
+    }
+
+    /**
+     * Creates a NavigatorView for some given information.
+     * The type is used to determine a NavigatorView class within the
+     * ClassLoader.
+     * 
+     * @param hs The HelpSet that provides context information.
+     * @param name The name of the View.
+     * @param label The label (to show the user) of the View.
+     * @param className The type for the View (its class name).
+     * @param params A hashtable that provides different key/values for this type.
+     * @return The desired NavigatorView object.
+     * @throws InvalidNavigatorViewException if <tt>hs</tt>, <tt>name</tt>, 
+     * <tt>label</tt>, <tt>locale</tt>, <tt>className</tt>, or <tt>params</tt> 
+     * are null, or if a valid NavigatorView cannot be constructed from the
+     * parameters.
+     */
+    public static NavigatorView create(HelpSet hs,
+				       String name,
+				       String label,
+				       Locale locale,
+				       String className,
+				       Hashtable params)
+	throws InvalidNavigatorViewException
+    {
+	ClassLoader loader;
+	Class klass;
+	NavigatorView back;
+
+        try {
+	    loader = hs.getLoader();
+            Constructor konstructor;
+	    Class types[] = { HelpSet.class,
+			      String.class, String.class, Locale.class,
+			      Hashtable.class };
+	    Object args[] = { hs,
+			      name, label, locale,
+			      params };
+	    if (loader == null) {
+	        klass = Class.forName(className);
+	    } else {
+	        klass = loader.loadClass(className);
+	    }
+	    konstructor = klass.getConstructor(types);
+	    back = (NavigatorView) konstructor.newInstance(args);
+	    return back;
+	} catch (Exception ex) {
+	    throw new InvalidNavigatorViewException("Could not create",
+						    hs,
+						    name, label, locale,
+						    className, params);
+	}
+    }
+
+    /**
+     * Creates a navigator for a given model.  Really a JHelpNavigator right now.
+     *
+     * @param model The model for the Navigator.
+     */
+    public abstract Component createNavigator(HelpModel model);
+
+ 
+
+    /**
+     * Gets the HelpSet for this Navigator view.
+     *
+     * @return the HelpSet
+     */
+    public HelpSet getHelpSet() {
+	return hs;
+    }
+
+    /**
+     * Gets the name of this Navigator view.
+     *
+     * @return the Name of the view
+     */
+    public String getName() {
+	return name;
+    }
+
+    /**
+     * Gets the locale-dependent name of this View.
+     *
+     * @return The locale-dependent name of this view.
+     */
+    public String getLabel(Locale locale) {
+	return getLabel();
+    }
+
+    /**
+     * Gets the locale-dependent name of this View 
+     *
+     * @return The locale-dependent name of this view
+     */
+    public String getLabel() {
+	return label;
+    }
+
+    /**
+     * @return The locale.
+     */
+    public Locale getLocale() {
+	return locale;
+    }
+
+    /**
+     * Gets parameters passed to this View.
+     *
+     * @return The parameters passed to this View.
+     */
+    public Hashtable getParameters() {
+	return params;
+    }
+    
+    /**
+     * Gets merge type of this Navigator view
+     *
+     * @return The merge type of this Navigator view
+     */ 
+    public String getMergeType(){
+        return mergeType;
+    }
+
+    /**
+     * Returns Map ID of icons passed to this View.
+     *
+     * @return the Map ID of icons passed to this View
+     */
+    public Map.ID getImageID() {
+        return imageID;
+    }
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/NoMerge.java b/jhMaster/JavaHelp/src/new/javax/help/NoMerge.java
new file mode 100644
index 0000000000000000000000000000000000000000..cef28b7645e4dcf1ed823dccac0799420bdd966d
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/NoMerge.java
@@ -0,0 +1,98 @@
+/*
+ * @(#)NoMerge.java	1.3 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help;
+
+import javax.swing.tree.*;
+import java.util.*;
+import java.text.*;
+
+/**
+ * No merge type
+ *
+ * @author Roger Brinkley
+ * @version	1.3	10/30/06
+ */
+public class NoMerge extends Merge{
+
+    /**
+     * Constructs NoMerge
+     *
+     * @param master The master NavigatorView
+     * @param slave The slave NavigatorView
+     */ 
+    public NoMerge(NavigatorView master, NavigatorView slave){
+        super(master,slave);
+
+    }
+    
+    /**
+     * Processes no merge
+     *
+     * @param node The master node
+     * @return the master node
+     */
+    public TreeNode processMerge(TreeNode node){
+       debug("start merge");
+       DefaultMutableTreeNode masterNode = (DefaultMutableTreeNode)node;
+ 
+       // There is no merging here but we will make sure
+       // the master children are handled correctly
+       MergeHelpUtilities.mergeNodeChildren("javax.help.NoMerge",
+					    masterNode);      
+       return masterNode;
+    }
+    
+    /**
+     * Merge Nodes. Merge two nodes according to the merging rules of the
+     * masterNode. Each Subclass should override this implementation.
+     *
+     * @param master The master node to merge with 
+     * @param slave The node to merge into the master
+     */
+    public static void mergeNodes(TreeNode master, TreeNode slave) {
+	// Doesn't do anything
+    }
+
+    /**
+     * Merge Node Children. Merge the children of a node according to the
+     * merging rules of the parent. Each subclass must implement this method
+     *
+     * @param node The parent node from which the children are merged
+     */
+    public static void mergeNodeChildren(TreeNode node) {
+	// Doesn't do anything
+    }
+    
+    private static boolean debug = false;
+    private static void debug(String msg){
+        if (debug) {
+            System.out.println("NoMerge :"+msg);
+	}
+    }
+}
+    
diff --git a/jhMaster/JavaHelp/src/new/javax/help/Popup.java b/jhMaster/JavaHelp/src/new/javax/help/Popup.java
new file mode 100644
index 0000000000000000000000000000000000000000..d3387b741184bdc273c09a962dd5a99c7ecc573d
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/Popup.java
@@ -0,0 +1,711 @@
+/*
+ * @(#)Popup.java	1.5 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help;
+
+import java.applet.Applet;
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.Rectangle;
+import java.awt.Dialog;
+import java.awt.Point;
+import java.awt.Toolkit;
+import java.awt.Window;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.ComponentAdapter;
+import java.awt.event.ComponentEvent;
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseWheelEvent;
+import java.awt.event.MouseWheelListener;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import javax.swing.BorderFactory;
+import javax.swing.JComponent;
+import javax.swing.JDialog;
+import javax.swing.JMenu;
+import javax.swing.JMenuItem;
+import javax.swing.JPopupMenu;
+import javax.swing.JRootPane;
+import javax.swing.JWindow;
+import javax.swing.JFrame;
+import javax.swing.KeyStroke;
+import javax.swing.SwingUtilities;
+import javax.swing.event.MouseInputAdapter;
+import java.lang.reflect.Method;
+import java.util.Vector;
+import com.sun.java.help.impl.JHSecondaryViewer;
+
+/**
+ * Popup is a Presentation class that will create a popup help window for an
+ * application. There is only one popup per application. A popup contains only
+ * a content viewer. It is intended to provide immediate help and then allow 
+ * the user to continue working. Once a popup loses focus, it is destroyed.
+ *
+ * @author Roger D. Brinkley
+ * @version	1.5	10/30/06
+ * @since 2.0
+ *
+ * @see javax.help.Presentation
+ */
+
+public class Popup extends Presentation implements ActionListener{
+
+    private JHelpContentViewer jheditor;
+    private Component invoker = null;
+    private JWindow window = null;
+    private Vector grabbed = null;
+    private PopupComponentAdapter pca= null;
+    private PopupKeyAdapter pka=null;
+    private PopupMouseAdapter pma=null;
+    private PopupMouseWheelListener pmwl=null;
+    private PopupWindowAdapter pwa=null;
+    private Rectangle internalBounds=null;
+    static private final String SHOW = "show";
+    static private final String CANCEL = "cancel";
+    static private boolean on1dot4 = false;
+
+    static {
+        try {
+            // Test if method introduced in 1.4 is available.
+	    Class klass = Class.forName("java.awt.event.MouseWheelEvent");
+            on1dot4 = (klass == null);
+        } catch (ClassNotFoundException e) {
+            on1dot4 = false;
+        }
+    }
+
+
+    /*
+     * The currentPopup is the Popup that is currently displayed on the
+     * screen. This state is maintained for positioning purposes when a 
+     * popup invokes a popup to use the currently displayed invoker rather
+     * than the invoker passed in.
+     */
+    static Popup currentPopup = null;
+
+    /*
+     * Private costructor
+     */
+    private Popup(HelpSet hs) {
+	setHelpSet(hs);
+    }
+
+    /**
+     * create a new Popup for a given HelpSet and HelpSet.Presentation 
+     * "name". If the "name"d HelpSet.Presentation does not exist in the
+     * HelpSet then the defaultHelpSet.Presentation if used.
+     *
+     * @param hs The HelpSEt used in this presentation
+     * @param name The name of the HelpSet.Presentation to use
+     * @returns Presentation A Popup.
+     */
+    static public Presentation getPresentation(HelpSet hs, String name) {
+
+	Popup thePopup = new Popup(hs);
+
+	if (hs != null) {
+	    HelpSet.Presentation presentation = null;
+
+	    // get a named presentation if one exists
+	    if (name != null) {
+		presentation = hs.getPresentation(name);
+	    }
+
+	    // get the default presentation if one exits
+	    if (presentation == null) {
+		presentation = hs.getDefaultPresentation();
+	    }
+
+	    // set the presentation
+	    // a null is ok here as it will just return.
+	    thePopup.setHelpSetPresentation(presentation);
+	}
+	return thePopup;
+    }
+
+    /**
+     * Get the Component that invoked this popup
+     *
+     * @return Component The invoking component
+     */
+    public Component getInvoker() {
+	return invoker;
+    }
+
+    /**
+     * Set the invoking component for this popup. This must be called before
+     * setDisplayed(true) is called. If there is an invoker already set it will
+     * be used instead of the new invoker.
+     * 
+     * @param invoker The component that invoked this popup
+     * @throws an IllegalArgumentException if the invoker or it's parents are
+     *		not showing.
+     */
+    public void setInvoker(Component invoker) {
+	this.invoker = invoker;
+	// If we have a JMenuItem circulate up to the JMenu
+	if (invoker instanceof JMenuItem) {
+	    while (!(this.invoker instanceof JMenu)) {
+		this.invoker = this.invoker.getParent();
+		if (this.invoker instanceof JPopupMenu) {
+		    this.invoker = ((JPopupMenu)this.invoker).getInvoker();
+		}
+	    }
+	}
+	if (this.invoker == null) {
+	    throw new IllegalArgumentException("invoker");
+	}
+    }
+
+
+    /**
+     * Get the internal bounds for the invoker.
+     */
+    public Rectangle getInvokerInternalBounds() {
+	return internalBounds;
+    }
+
+    /**
+     * Set the the internal bounds for an invoker. For some invokers like
+     * JTrees and JTables it is necessary to set an internal bounds to 
+     * further define the location of where to place the popup.
+     *
+     * @param bounds A Rectangle of the internal bounds
+     */
+    public void setInvokerInternalBounds(Rectangle bounds) {
+	internalBounds = bounds;
+    }
+
+    /**
+     * return the JWindow if created. Will return a null if not created.
+     */
+    private JWindow getWindow() {
+	return window;
+    }
+
+    /**
+     * Displays the presentation to the user
+     */
+    public void setDisplayed(boolean b) {
+	Container top = getTopMostContainer();
+
+	// if the window is null and they don't want it displayed just return
+	if (window == null && !b) {
+	    return;
+	}
+
+	// if window is null create the window
+	if (window == null) {
+	    window = new JWindow((Window)getTopMostContainer());
+	    jheditor = new JHelpContentViewer(getHelpModel());
+	    window.getRootPane().setBorder(BorderFactory.createLineBorder(Color.black, 2));
+
+	    window.getContentPane().add(jheditor, BorderLayout.CENTER);
+	}
+	if (grabbed == null) {
+	    grabbed = new Vector();
+	    pca = new PopupComponentAdapter();
+	    pma = new PopupMouseAdapter();
+	    pwa = new PopupWindowAdapter();
+	    pka = new PopupKeyAdapter();
+	    if (on1dot4) {
+		pmwl = new PopupMouseWheelListener();
+	    }
+	} else {
+	    grabbed.clear();
+	}
+	grabContainer(top);
+	window.addWindowListener(pwa);
+	if (on1dot4) {
+	    try {
+		Class types[] = { Class.forName("java.awt.event.WindowFocusListener") };
+		Object args[] = { pwa };
+		Method m = window.getClass().getMethod("addWindowFocusListener", types);
+		m.invoke(window, args);
+		// window.addWindowFocusListener(pwa);
+	    } catch (java.lang.Exception ex) {
+		//ignore it
+	    }
+	}
+
+	JRootPane root = getRootPane();
+	if (root != null) {
+	    root.registerKeyboardAction(this, "cancel",
+					KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0),
+					JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
+	} else if (top != null) {
+	    top.addKeyListener(pka);
+	}
+	window.getRootPane().registerKeyboardAction(this, "cancel",
+						    KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0),
+						    JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
+	
+	if (b) {
+	    showPopup();
+	} else {
+	    cancelPopup();
+	}
+    }
+
+    public boolean isDisplayed() {
+	if (window != null) {
+	    return true;
+	}
+	return false;
+    }
+
+    public void actionPerformed(ActionEvent e) {
+	String command = e.getActionCommand();
+        if (command == "cancel") {
+	    cancelPopup();
+        }
+    }
+
+    /**
+     * show the window
+     */
+    private void showPopup() {
+	if (currentPopup != null &&
+	    SwingUtilities.getAncestorOfClass(JWindow.class, invoker) == 
+	    currentPopup.getWindow()) {
+	    setInvoker(currentPopup.getInvoker());
+	}
+
+        Rectangle popupBounds = computePopupBounds(getSize());
+
+	jheditor.setPreferredSize(new Dimension(popupBounds.width, 
+						popupBounds.height));
+	window.setBounds(popupBounds.x, popupBounds.y, 
+			 popupBounds.width, popupBounds.height);
+	window.pack();
+	window.show();
+	currentPopup = this;
+    }
+
+    private Rectangle computePopupBounds(Dimension popupSize) {
+	// Note all Points in computePopupBounds are either relative to
+	// the screen. The desired boundry must fit on the screen. If it is
+	// in a Modal Dialg it has to fit within the dialog
+
+        Rectangle absBounds;
+	Point p;
+
+	// Calculate the absolute boundry. Modal Dialogs must be within the 
+	// Dialog.
+        boolean inModalDialog = inModalDialog();
+
+        /** Workaround for modal dialogs. See also JPopupMenu.java **/
+        if ( inModalDialog ) {
+            Dialog dlg = getDialog();
+            if ( dlg instanceof JDialog ) {
+                JRootPane rp = ((JDialog)dlg).getRootPane();
+                p = rp.getLocationOnScreen();
+                absBounds = rp.getBounds();
+                absBounds.x = p.x;
+                absBounds.y = p.y;
+            } else {
+                absBounds = dlg.getBounds();
+	    }
+        } else {
+            Dimension scrSize = Toolkit.getDefaultToolkit().getScreenSize();
+            absBounds = new Rectangle(0, 0, scrSize.width, scrSize.height);
+        }
+
+	if (internalBounds == null) {
+	    internalBounds = invoker.getBounds();
+	}
+	debug("\nabsBounds=" + absBounds + "\ninternalBounds=" + internalBounds + "\n");
+
+	// Get a rectangle below and to the right and see if it fits
+	p = new Point(internalBounds.x, 
+		      internalBounds.y + internalBounds.height);
+	SwingUtilities.convertPointToScreen(p, invoker);
+        Rectangle br = new Rectangle(p.x, p.y, 
+				     popupSize.width, popupSize.height);
+	debug("below/right " + br + "\n");
+        if ( SwingUtilities.isRectangleContainingRectangle(absBounds, br) ) {
+	    // below and to the right fits return the rectangle
+            return br;
+        }
+
+	// below and right failed - try to adjust the right side to fit
+	Rectangle bradjust = new Rectangle(br);
+	bradjust.setLocation(br.x + internalBounds.width - br.width, 
+			     br.y);
+	debug("below/right adjust " + bradjust + "\n");
+	if ( SwingUtilities.isRectangleContainingRectangle(absBounds, 
+							   bradjust) ) {
+	    // below and to the right fits return the rectangle
+            return bradjust;
+	} 
+
+	// below and right adjust failed - try above right
+	Rectangle ar = new Rectangle(br.x, 
+				     br.y-(br.height+internalBounds.height),
+				     br.width, br.height);
+	debug("above/right " + ar + "\n");
+	if (SwingUtilities.isRectangleContainingRectangle(absBounds, ar)) {
+	    // above and to the right fits return the rectangle
+            return ar;
+	} 
+
+	// above and right failed - adjust the right side to fit
+	Rectangle aradjust = new Rectangle(ar);
+	aradjust.setLocation(ar.x + internalBounds.width - ar.width, 
+			     aradjust.y);
+	debug("above/right adjust " + aradjust + "\n");
+	if ( SwingUtilities.isRectangleContainingRectangle(absBounds, 
+							   aradjust) ) {
+	    // below and to the right fits return the rectangle
+            return aradjust;
+	} 
+
+	// above and right adjust failed - try right below
+	p = new Point(internalBounds.x + internalBounds.width, 
+		      internalBounds.y);
+	SwingUtilities.convertPointToScreen(p, invoker);
+	Rectangle rb = new Rectangle(p.x, p.y, 
+				     popupSize.width, popupSize.height);
+	debug("right/below " + rb + "\n");
+	if (SwingUtilities.isRectangleContainingRectangle(absBounds, rb)) {
+	    // right and below fits return the rectangle
+            return rb;
+	} 
+
+	// right and below failed - adjust the top side to fit
+	Rectangle rbadjust = new Rectangle(rb);
+	rbadjust.setLocation(rbadjust.x,
+			     rb.y + internalBounds.height - rb.height);
+	debug("right/below adjust " + rbadjust + "\n");
+	if ( SwingUtilities.isRectangleContainingRectangle(absBounds,
+							   rbadjust) ) {
+	    // right and below adjusted fits return the rectangle
+            return rbadjust;
+	} 
+
+	// right and below adjust failed - try left and below
+	Rectangle lb = new Rectangle(rb.x-(rb.width+internalBounds.width), 
+				     rb.y,
+				     rb.width, rb.height);
+	debug("left/below " + lb + "\n");
+	if (SwingUtilities.isRectangleContainingRectangle(absBounds, lb)) {
+	    // right and below fits return the rectangle
+            return lb;
+	} 
+
+	// left and below failed - adjust the top side to fit
+	Rectangle lbadjust = new Rectangle(lb);
+	lbadjust.setLocation(lbadjust.x,
+			     lb.y + internalBounds.height - lb.height);
+	debug("left/below adjust " + lbadjust + "\n");
+	if ( SwingUtilities.isRectangleContainingRectangle(absBounds, 
+							   lbadjust) ) {
+	    // right and below fits return the rectangle
+            return lbadjust;
+	} 
+
+	// Bummer - tried all around the object so no try covering it up
+	// Nothing fancy here upper left corner
+	Rectangle cover = new Rectangle(0, 0, 
+					popupSize.width, 
+					popupSize.height);
+	debug("upper left hand corner " + cover + "\n");
+	if (SwingUtilities.isRectangleContainingRectangle(absBounds, cover)) {
+	    // covering up the object fits return the rectangle
+            return cover;
+	} 
+
+	// Humm. The desired size is just to large. Shrink to fit.
+	SwingUtilities.computeIntersection(absBounds.x,
+					   absBounds.y,
+					   absBounds.width,
+					   absBounds.height,
+					   cover);
+	return cover;
+    }
+
+    private Container getTopMostContainer() {
+	if (invoker == null) {
+	    return null;
+	}
+	
+        for(Container p=((invoker instanceof Container) ? (Container)invoker :
+			 invoker.getParent());
+			 p != null; p = p.getParent()) {
+	    if (p instanceof JPopupMenu) {
+		Component comp = ((JPopupMenu)p).getInvoker();
+		if (comp instanceof Container) {
+		    p = (Container) comp;
+		}
+	    }
+            if (p instanceof Window || p instanceof Applet) {
+                return p;
+            }
+        }
+        return null;
+    }
+	
+    private JRootPane getRootPane() {
+	Container parent = null;
+	JRootPane pane = null;
+	if (invoker == null || !(invoker instanceof JComponent)) {
+	    return null;
+	}
+
+	pane = ((JComponent)invoker).getRootPane();
+	if (pane != null) {
+	    return pane;
+	}
+	
+	// for loop through the parents until you reach a Dialog or null
+        for ( parent = ((invoker instanceof Container) ? (Container)invoker : 
+		  invoker.getParent()); 
+	      parent != null && !(parent instanceof JDialog) && 
+		  !(parent instanceof JWindow) && !(parent instanceof JFrame) ; 
+	      parent = parent.getParent() ) {
+	    if (parent instanceof JPopupMenu) {
+		Component comp = ((JPopupMenu)parent).getInvoker();
+		if (comp instanceof Container) {
+		    parent = (Container) comp;
+		}
+	    }
+	}
+
+	if (parent instanceof JFrame) {
+	    pane = ((JFrame)parent).getRootPane();
+	} else if (parent instanceof JWindow) {
+	    pane = ((JWindow)parent).getRootPane();
+	} else if (parent instanceof JDialog) {
+	    pane = ((JDialog)parent).getRootPane();
+	}
+
+	return pane;
+    }
+	
+
+    /*
+     * Get the Dialog from the invoker
+     */
+    private Dialog getDialog() {
+	Container parent;
+	if (invoker == null) {
+	    return null;
+	}
+	
+	// for loop through the parents until you reach a Dialog or null
+        for ( parent = ((invoker instanceof Container) ? (Container)invoker : 
+		  invoker.getParent()); 
+	      parent != null && !(parent instanceof Dialog) ; 
+	      parent = parent.getParent() );
+
+	// return the dialog if we got one
+        if ( parent instanceof Dialog )
+            return (Dialog) parent;
+        else
+            return null;
+    }
+
+    private boolean inModalDialog() {
+        return (getDialog() != null);
+    }
+
+    private class PopupWindowAdapter extends WindowAdapter {
+
+	public void windowClosing(WindowEvent e) {
+	    cancelPopup();
+	}
+
+	public void windowClosed(WindowEvent e) {
+	    cancelPopup();
+	}
+
+	public void windowIconified(WindowEvent e) {
+	    cancelPopup();
+	}
+
+	public void windowGainedFocus(WindowEvent e) {
+	    window.toFront();
+	}
+
+    }
+
+    private class PopupMouseAdapter extends MouseInputAdapter {
+
+	public void mousePressed(MouseEvent e) {
+	    cancelPopup();
+	}
+    }
+
+    private class PopupMouseWheelListener implements MouseWheelListener {
+	public void mouseWheelMoved(MouseWheelEvent e) {
+	    cancelPopup();
+	}
+    }
+    
+    private class PopupComponentAdapter extends ComponentAdapter {
+
+	public void componentResized(ComponentEvent e) {
+	    cancelPopup();
+	}
+
+	public void componentMoved(ComponentEvent e) {
+	    cancelPopup();
+	}
+
+	public void componentShown(ComponentEvent e) {
+	    cancelPopup();
+	}
+
+	public void componentHidden(ComponentEvent e) {
+	    cancelPopup();
+	}
+
+    }
+    
+    /*
+     * Only used for AWT components
+     */
+    private class PopupKeyAdapter extends KeyAdapter {
+
+	public void keyReleased(KeyEvent e) {
+	    int code = e.getKeyCode();
+	    if (code == KeyEvent.VK_ESCAPE) {
+		cancelPopup();
+	    }
+	}
+    }
+ 
+   private void grabContainer (Container c) {
+	if(c instanceof java.awt.Window) {
+	    ((java.awt.Window)c).addWindowListener(pwa);
+	    ((java.awt.Window)c).addComponentListener(pca);
+	    grabbed.addElement(c);
+	}
+	synchronized(c.getTreeLock()) {
+	    int ncomponents = c.getComponentCount();
+	    Component[] component = c.getComponents();
+	    for (int i = 0 ; i < ncomponents ; i++) {
+		Component comp = component[i];
+		if(!comp.isVisible())
+		    continue;
+		comp.addMouseListener(pma);
+		comp.addMouseMotionListener(pma);
+		if (on1dot4) {
+		    try {
+			Class types[] = { Class.forName("java.awt.event.MouseWheelListener") };
+			Object args[] = { pmwl };
+			Method m = window.getClass().getMethod("addMouseWheelListener", types);
+			m.invoke(comp, args);
+			// comp.addMouseWheelListener(pmwl);
+		    } catch (java.lang.Exception ex) {
+			//ignore it
+		    }
+		}
+		grabbed.addElement(comp);
+		if (comp instanceof Container) {
+		    Container cont = (Container) comp;
+		    grabContainer(cont);
+		}
+	    }
+	}
+    }
+	
+    void ungrabContainers() {
+	int i,c;
+	Component cpn;
+	for(i=0,c=grabbed.size();i<c;i++) {
+	    cpn = (Component)grabbed.elementAt(i);
+	    if(cpn instanceof java.awt.Window) {
+		((java.awt.Window)cpn).removeWindowListener(pwa);
+		((java.awt.Window)cpn).removeComponentListener(pca);
+	    } else {
+		cpn.removeMouseListener(pma);
+		cpn.removeMouseMotionListener(pma);
+		if (on1dot4) {
+		    try {
+			Class types[] = { Class.forName("java.awt.event.MouseWheelListener") };
+			Object args[] = { pmwl };
+			Method m = window.getClass().getMethod("removeMouseWheelListener", types);
+			m.invoke(cpn, args);
+			// cpn.removeMouseWheelListener(pmwl);
+		    } catch (java.lang.Exception ex) {
+			//ignore it
+		    }
+		}
+	    }
+	}
+	grabbed = null;
+    }
+	
+    private void cancelPopup() {
+	Container top = getTopMostContainer();
+	ungrabContainers();
+	JRootPane root = getRootPane();
+	if (root != null) {
+	    root.unregisterKeyboardAction
+		(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0));
+	} else if (top != null) {
+	    top.removeKeyListener(pka);
+	}
+	window.removeWindowListener(pwa);
+	if (on1dot4) {
+	    try {
+		Class types[] = { Class.forName("java.awt.event.WindowFocusListener") };
+		Object args[] = { pwa };
+		Method m = window.getClass().getMethod("removeWindowFocusListener", types);
+		m.invoke(window, args);
+		// window.removeWindowFocusListener(pwa);
+	    } catch (java.lang.Exception ex) {
+		//ignore it
+	    }
+	}
+	window.getRootPane().unregisterKeyboardAction
+	    (KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0));
+	window.dispose();
+	window = null;
+	jheditor = null;
+	currentPopup = null;
+    }
+	
+    /**
+     * Debugging code...
+     */
+
+    private static final boolean debug = false;
+    private static void debug(Object msg) {
+	if (debug) {
+	    System.err.println("Popup: "+msg);
+	}
+    }
+
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/Presentation.java b/jhMaster/JavaHelp/src/new/javax/help/Presentation.java
new file mode 100644
index 0000000000000000000000000000000000000000..183c382b96060142752d1965c2671850e8039485
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/Presentation.java
@@ -0,0 +1,309 @@
+/*
+ * @(#)Presentation.java	1.5 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help;
+
+import java.util.Locale;
+import java.awt.Font;
+import java.awt.Dimension;
+import javax.help.Map.ID;
+import java.net.URL;
+
+
+/**
+ * Presentation is an abstract class providing a generic interface for
+ * the development of alternative Presentations. Each implementation of 
+ * Presentation will need to override the static method getPresentation
+ * according to it's own needs. For instance Popup creates a single object
+ * whereas SecondaryWindow looks for an existing secondary window that matches
+ * the parameters before creating a new SecondaryWindow and MainWindow will
+ * always create a new Presentation.
+ *
+ * Presentation implements several generic methods required in all 
+ * presentations.
+ *
+ * @author Roger D.Brinkley
+ * @version	1.5	10/30/06
+ * @since 2.0
+ *
+ * @see javax.help.HelpSet
+ */
+
+public abstract class Presentation {
+
+    private HelpSet helpset = null;
+    private TextHelpModel model = null;
+    private Locale locale = null;
+    private Font font = null;
+    private int width = 645;
+    private int height = 495;
+
+    /**
+     * Get a "name" Presentation given the passed HelpSet.
+     * The presentation returned will vary depending on the implementing
+     * class. All classes will set the HelpSetPresentation based on the
+     * name if a HelpSet.Presentation matching that name exists in the
+     * HelpSet. If no named HelpSet.Presentation exits the default
+     * HelpSet.Presentation is used if present, otherwise the implementing
+     * class defaults will be used.
+     * Implementation of Presentation will
+     * override this implementation to return their own type. Implementation 
+     * also have the descression to reuse "name"d presentations or create
+     * new Presentations. Presentation will return null unless otherwise 
+     * overriden.
+     * 
+     * @param hs The helpset used to get the Presentation
+     * @param name The name of the presentation.
+     */
+    static public Presentation getPresentation(HelpSet hs, String name) {
+	return null;
+    }
+
+    /**
+     * Set the Presentation attributes from a named presentation in a HelpSet.
+     * Extension of this class should extend this class by adding additional
+     * attributes 
+     * 
+     * @params hsPres - the HelpSet.Presentation to retrieve the presentation 
+     *                  information from
+     * 
+     * @see HelpSet.Presentation
+     */
+    public void setHelpSetPresentation (HelpSet.Presentation hsPres) {
+	debug("setHelpSetPresentation");
+	if (hsPres == null) {
+	    return;
+	}
+
+	// get the presentation size
+	Dimension size = hsPres.getSize();
+	if (size != null) {
+	    setSize(size);
+	}
+
+    }
+
+    /**
+     * Determines which ID is displayed (if any).
+     * @returns the current ID or null if there is none
+     */
+    public ID getCurrentID() {
+	debug("getCurrentID");
+	if (model != null) {
+	    return model.getCurrentID();
+	}
+	return null;
+    }
+
+    /**
+     * Shows this ID as content relative to the (top) HelpSet for the Presentation
+     * instance--HelpVisitListeners are notified.
+     *
+     * @param id A string that identifies the topic to show for the loaded (top) HelpSet
+     * @exception BadIDException The ID is not valid for the HelpSet
+     */
+    public void setCurrentID(String id) throws BadIDException {
+	debug("setCurrentID - String");
+	try {
+	    setCurrentID(ID.create(id, helpset));
+	} catch (InvalidHelpSetContextException ex) {
+	    // this should not happen
+	    new Error("internal error?");
+	}
+    }
+
+    /**
+     * Displays this ID--HelpVisitListeners are notified.
+     *
+     * @param id a Map.ID indicating the URL to display
+     * @exception InvalidHelpSetContextException if the current helpset does not contain
+     * id.helpset
+     */
+    public void setCurrentID(ID id) throws InvalidHelpSetContextException {
+	debug("setCurrentID - ID");
+
+	createHelpModel();
+	model.setCurrentID(id);
+    }
+
+    /**
+     * Determines which URL is displayed.
+     */
+    public URL getCurrentURL() {
+	debug("getCurrentURL");
+	if (model != null) {
+	    return model.getCurrentURL();
+	}
+	return null;
+    }
+
+
+    /**
+     * sets the current URL.
+     * HelpVisitListeners are notified.
+     * The currentID changes if there is a mathing ID for this URL
+     * @param url The url to display. A null URL is a valid url.
+     */
+    public void setCurrentURL(URL url) {
+	debug("setCurrentURL");
+	createHelpModel();
+	model.setCurrentURL(url);
+    }
+
+    /**
+     * Returns the default HelpSet
+     */
+    public HelpSet getHelpSet() {
+	debug("getHelpSet");
+	return helpset;
+    }
+
+    /**
+     * Changes the HelpSet for this presentation.
+     * @param hs The HelpSet to set for this presentation. 
+     * A null hs is valid parameter.
+     */
+    public void setHelpSet(HelpSet hs) {
+	debug("setHelpSet");
+	// If we already have a model check if the HelpSet has changed.
+	// If so change the model
+	// This could be made smarter to cache the helpmodels per HelpSet
+	if (hs != null && helpset != hs) {
+	    model = new DefaultHelpModel(hs);
+	    helpset = hs;
+            
+	}
+    }
+
+    /**
+     * Displays the presentation to the user.
+     */
+    abstract public void setDisplayed(boolean b);
+
+    /**
+     * Determines if the presentation is displayed.
+     */
+    abstract public boolean isDisplayed();
+
+    /**
+     * Gets the font for this Presentation.
+     */
+    public Font getFont () {
+	debug("getFont");
+	return font;
+    }
+
+    /**
+     * Sets the font for this this Presentation. Concrete implementations must
+     * make sure that the font is properly set by extending this class.
+     * @param f The font.
+     */
+    public void setFont (Font f) {
+	debug("setFont");
+	font = f;
+    }
+
+    /**
+     * Gets the locale of this component.
+     * @return This component's locale. If this component does not
+     * have a locale, the defaultLocale is returned.
+     * @see #setLocale
+     */
+    public Locale getLocale() {
+	debug("getLocale");
+	if (locale == null) {
+	  return Locale.getDefault();
+	}
+	return locale;
+    }
+
+    /**
+     * Sets the locale of this Presentation. The locale is propagated to
+     * the presentation. Concrete implemenation must make sure they override
+     * this class to properly set the locale.
+     *
+     * @param l The locale to become this component's locale. A null locale
+     * is the same as the defaultLocale.
+     * @see #getLocale
+     */
+    public void setLocale(Locale l) { 
+	debug("setLocale");
+	locale = l;
+    }
+
+    /**
+     * Requests the size of the presentation.
+     * @returns Point the location of the presentation.
+     */
+    public Dimension getSize() {
+	debug("getSize");
+	return new Dimension(width, height);
+    }
+
+    /**
+     * Requests the presentation be set to a given size.
+     * Concrete implementation must override this method to properly set the
+     * size.
+     * 
+     * @param d - a Dimension to set the size to.
+     */
+    public void setSize(Dimension d) {
+	debug("setSize");
+	width = d.width;
+	height = d.height;
+    }
+
+    /*
+     * private implementations
+     */
+    private void createHelpModel() {
+	if (model == null) {
+	    model = new DefaultHelpModel(helpset);
+	}
+    }
+
+    protected TextHelpModel getHelpModel () {
+	if (model == null) {
+	    createHelpModel();
+	}
+	return model;
+    }
+
+    /**
+     * Debugging code...
+     */
+
+    private static final boolean debug = false;
+    private static void debug(Object msg) {
+	if (debug) {
+	    System.err.println("Presentation: "+msg);
+	}
+    }
+ 
+}
+
+
diff --git a/jhMaster/JavaHelp/src/new/javax/help/PrintAction.java b/jhMaster/JavaHelp/src/new/javax/help/PrintAction.java
new file mode 100644
index 0000000000000000000000000000000000000000..b4706828a936e1fd90df5a4d2f5bb7cb3dfe4fc8
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/PrintAction.java
@@ -0,0 +1,107 @@
+/*
+ * @(#)PrintAction.java	1.3 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.net.URL;
+import java.util.Locale;
+import javax.swing.UIManager;
+import com.sun.java.help.impl.JHelpPrintHandler;
+
+/**
+ *
+ * @author Stepan Marek
+ * @version	1.3	10/30/06
+ */
+public class PrintAction extends AbstractHelpAction implements PropertyChangeListener, ActionListener {
+
+    private static final String NAME = "PrintAction";
+    
+    private JHelpPrintHandler handler = null;
+
+    /** Creates new BackAction */
+    public PrintAction(Object control) {
+        
+        super(control, NAME);
+        
+        if (control instanceof JHelp) {
+            
+            JHelp help = (JHelp)control;
+            
+            handler = JHelpPrintHandler.getJHelpPrintHandler(help);
+            handler.addPropertyChangeListener(this);
+            
+	    Locale locale = null;
+	    try {
+		locale = help.getModel().getHelpSet().getLocale();
+	    } catch (NullPointerException npe) {
+		locale = Locale.getDefault();
+	    }
+            putValue("tooltip", HelpUtilities.getString(locale, "tooltip." + NAME));
+            putValue("access", HelpUtilities.getString(locale, "access." + NAME));
+
+        }
+        
+        putValue("icon", UIManager.getIcon(NAME + ".icon"));
+        
+    }
+
+    public void actionPerformed(ActionEvent event) {
+        if (handler != null) {
+            JHelp help = (JHelp)getControl();
+            URL[] urls = null;
+            TreeItem[] items = help.getSelectedItems();
+            if (items != null) {
+                urls = new URL[items.length];
+                for (int i = 0; i < items.length; i++) {
+                    urls[i] = items[i].getURL();
+                }
+            }
+            if ((urls != null) && (urls.length > 0)) {
+                handler.print(urls);
+            } else {
+                handler.print(help.getModel().getCurrentURL());
+            }
+        }
+    }
+    
+        
+    /**
+     * This method gets called when a bound property is changed.
+     * @param evt A PropertyChangeEvent object describing the event source
+     *  	and the property that has changed.
+     */
+    public void propertyChange(PropertyChangeEvent evt) {
+        if (evt.getPropertyName().equals("enabled")) {
+            setEnabled(((Boolean)evt.getNewValue()).booleanValue());
+        }
+    }
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/PrintSetupAction.java b/jhMaster/JavaHelp/src/new/javax/help/PrintSetupAction.java
new file mode 100644
index 0000000000000000000000000000000000000000..3bb6b85b1b8b3d617f2a6d9269bbfd93b8636f34
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/PrintSetupAction.java
@@ -0,0 +1,92 @@
+/*
+ * @(#)PrintSetupAction.java	1.3 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.util.Locale;
+import javax.swing.UIManager;
+import com.sun.java.help.impl.JHelpPrintHandler;
+
+/**
+ *
+ * @author Stepan Marek
+ * @version	1.3	10/30/06
+ */
+public class PrintSetupAction extends AbstractHelpAction implements PropertyChangeListener, ActionListener {
+    
+    private static final String NAME = "PrintSetupAction";
+    
+    private JHelpPrintHandler handler = null;
+    
+    /** Creates new BackAction */
+    public PrintSetupAction(Object control) {
+        
+        super(control, NAME);
+        
+        if (getControl() instanceof JHelp) {
+            
+            JHelp help = (JHelp)control;
+            
+            handler = JHelpPrintHandler.getJHelpPrintHandler(help);
+            handler.addPropertyChangeListener(this);
+            
+	    Locale locale = null;
+	    try {
+		locale = help.getModel().getHelpSet().getLocale();
+	    } catch (NullPointerException npe) {
+		locale = Locale.getDefault();
+	    }
+            putValue("tooltip", HelpUtilities.getString(locale, "tooltip." + NAME));
+            putValue("access", HelpUtilities.getString(locale, "access." + NAME));
+
+        }
+        
+        putValue("icon", UIManager.getIcon(NAME + ".icon"));
+
+    }
+
+    public void actionPerformed(ActionEvent event) {
+        if (handler != null) {
+            handler.printSetup();
+        }
+    }
+    
+    /**
+     * This method gets called when a bound property is changed.
+     * @param evt A PropertyChangeEvent object describing the event source
+     *  	and the property that has changed.
+     */
+    public void propertyChange(PropertyChangeEvent evt) {
+        if (evt.getPropertyName().equals("enabled")) {
+            setEnabled(((Boolean)evt.getNewValue()).booleanValue());
+        }
+    }
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/ReloadAction.java b/jhMaster/JavaHelp/src/new/javax/help/ReloadAction.java
new file mode 100644
index 0000000000000000000000000000000000000000..e021e21f1483b2b4033100e88b355d4cdb207382
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/ReloadAction.java
@@ -0,0 +1,73 @@
+/*
+ * @(#)ReloadAction.java	1.3 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.help.*;
+import javax.help.event.*;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.Stack;
+import javax.swing.*;
+
+/**
+ *
+ * @author Roger Brinkley
+ * @version	1.3	10/30/06
+ */
+public class ReloadAction extends AbstractHelpAction implements ActionListener {
+    
+    private static final String NAME = "ReloadAction";
+    
+    /** Creates new ReloadAction */
+    public ReloadAction(Object control) {
+        super(control, NAME);
+        
+        putValue("icon", UIManager.getIcon(NAME + ".icon"));
+        
+        if (control instanceof JHelp) {
+	    JHelp help = (JHelp) control;
+	    Locale locale = null;
+	    try {
+		locale = help.getModel().getHelpSet().getLocale();
+	    } catch (NullPointerException npe) {
+		locale = Locale.getDefault();
+	    }
+
+            putValue("tooltip", HelpUtilities.getString(locale, "tooltip." + NAME));
+            putValue("access", HelpUtilities.getString(locale, "access." + NAME));
+        }
+    }
+    
+    public void actionPerformed(java.awt.event.ActionEvent event) {
+	JHelp help = (JHelp)getControl();
+	JHelpContentViewer viewer = help.getContentViewer();
+	viewer.reload();
+    }
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/SearchHit.java b/jhMaster/JavaHelp/src/new/javax/help/SearchHit.java
new file mode 100644
index 0000000000000000000000000000000000000000..b543ac8807b9eea67a5a81dcaab750130dcb6858
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/SearchHit.java
@@ -0,0 +1,64 @@
+/*
+ * @(#)SearchHit.java	1.4 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+/*
+ * @(#) SearchHit.java 1.4 - last change made 10/30/06
+ */
+
+package javax.help;
+
+/**
+ * Stores search information for individual Search hits.
+ *
+ * @author Roger D. Brinkley
+ * @version   1.4     10/30/06
+ */
+
+public class SearchHit {
+
+    private double confidence;
+    private int begin;
+    private int end;
+
+    public SearchHit(double confidence, int begin, int end) {
+	this.confidence = confidence;
+	this.begin = begin;
+	this.end = end;
+    }
+
+    public double getConfidence() {
+	return confidence;
+    }
+
+    public int getBegin() {
+	return begin;
+    }
+
+    public int getEnd() {
+	return end;
+    }
+}
+
diff --git a/jhMaster/JavaHelp/src/new/javax/help/SearchTOCItem.java b/jhMaster/JavaHelp/src/new/javax/help/SearchTOCItem.java
new file mode 100644
index 0000000000000000000000000000000000000000..edc03d8aaabb3c16dace96048c984ebd9077ea88
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/SearchTOCItem.java
@@ -0,0 +1,152 @@
+/*
+ * @(#)SearchTOCItem.java	1.9 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+/*
+ * @(#) SearchTOCItem.java 1.9 - last change made 10/30/06
+ */
+
+package javax.help;
+
+import java.net.URL;
+import java.net.MalformedURLException;
+import java.util.Vector;
+import java.util.Enumeration;
+import java.util.NoSuchElementException;
+import java.util.Locale;
+import javax.help.Map.ID;
+import javax.help.search.SearchItem;
+
+/**
+ * Stores Search TOC items. This class extends TOCItems with additonal
+ * search hits. Can be used as part of the TOC tree or as an appendage to
+ * the tree for items not contained in the tree.
+ *
+ * @author Roger D. Brinkley
+ * @version   1.9     10/30/06
+ */
+
+public class SearchTOCItem extends TOCItem {
+
+    private URL url;
+    private Vector sivec;
+    private boolean inTOC;
+    private double confidence;
+
+    public SearchTOCItem(ID id, ID imageID, HelpSet hs, Locale locale) {
+	super (id, imageID, hs, locale);
+	inTOC = true;
+	this.url = null;
+	sivec = new Vector();
+	confidence = 0;
+    }
+
+    // SearchItem should handle Locale, no Lang
+    public SearchTOCItem(SearchItem item) {
+	super (null, null, null, HelpUtilities.localeFromLang(item.getLang()));
+	inTOC = false;
+	setName(item.getTitle());
+	try {
+	    this.url = new URL(item.getBase(), item.getFilename());
+	} catch (MalformedURLException me) {
+	    this.url = null;
+	}
+	sivec = new Vector();
+	SearchHit info = new SearchHit(item.getConfidence(),
+					 item.getBegin(),
+					 item.getEnd());
+	confidence = item.getConfidence();
+	sivec.addElement(info);
+    }
+
+    /**
+     * Adds a SearchHit.
+     */
+    public void addSearchHit(SearchHit si) {
+	// these are in sorted order so look at the bottom
+	// entry first
+	//
+	// This sorted order needs to be looked at for FCS
+	if (sivec.isEmpty()) {
+	    sivec.addElement(si);
+	    confidence = si.getConfidence();
+	} else {
+	    for (int i = sivec.size() - 1; i >= 0 ; i--) {
+		SearchHit test = (SearchHit)sivec.elementAt(i);
+		if (test.getConfidence() <= si.getConfidence()) {
+		    sivec.insertElementAt(si, i+1);
+		    break;
+		}
+		if (i == 0) {
+		    sivec.insertElementAt(si, 0);
+		    confidence = si.getConfidence();
+		}
+	    }
+	}
+    }
+
+    public URL getURL() {
+	return url;
+    }
+
+    public double getConfidence() {
+	// The confidence level is the max confidence value
+	// The max value is determined at the time a Search Hit is
+	// added
+	return confidence;
+    }
+
+    public Enumeration getConfidences() {
+	return new Enumeration() {
+	    int count = 0;
+		
+	    public boolean hasMoreElements() {
+		return count < sivec.size();
+	    }
+		
+	    public Object nextElement() {
+		synchronized (sivec) {
+		    if (count < sivec.size()) {
+			return new Double(((SearchHit)sivec.elementAt(count++)).getConfidence());
+		    }
+		}
+		throw new NoSuchElementException("Vector Enumeration");
+	    }
+	};
+    }
+
+    public boolean inTOC() {
+	return inTOC;
+    }
+
+    public Enumeration getSearchHits() {
+	return sivec.elements();
+    }
+
+    public int hitCount() {
+	return sivec.size();
+    }
+}
+
diff --git a/jhMaster/JavaHelp/src/new/javax/help/SearchView.java b/jhMaster/JavaHelp/src/new/javax/help/SearchView.java
new file mode 100644
index 0000000000000000000000000000000000000000..d24b8c611d9557694196c22a5c67dd49eeae704a
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/SearchView.java
@@ -0,0 +1,84 @@
+/*
+ * @(#)SearchView.java	1.10 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help;
+
+import java.util.Hashtable;
+import java.awt.Component;
+import java.util.Locale;
+
+/**
+ * Navigational View information for a Search
+ *
+ * @author Eduardo Pelegri-Llopart
+ * @version	1.5	01/29/99
+ */
+
+public class SearchView extends NavigatorView {
+    /**
+     * Constructs a SearchView with some given data.  Locale of the View defaults
+     * to that of the HelpSet.
+     *
+     * @param hs The HelpSet that provides context information.
+     * @param name The name of the View.
+     * @param label The label (to show the user) of the View.
+     * @param locale The default locale to interpret the data in this TOC.
+    * @param params A hashtable that provides different key/values for this type.
+    */
+    public SearchView(HelpSet hs,
+		      String name,
+		      String label,
+		      Hashtable params) {
+	super(hs, name, label, hs.getLocale(), params);
+    }
+
+    /**
+     * Constructs a SearchView with some given data.
+     *
+     * @param hs The HelpSet that provides context information.
+     * @param name The name of the View.
+     * @param label The label (to show the user) of the View.
+     * @param locale The default locale to interpret the data in this TOC.
+    * @param params A hashtable that provides different key/values for this type.
+    */
+    public SearchView(HelpSet hs,
+		      String name,
+		      String label,
+		      Locale locale,
+		      Hashtable params) {
+	super(hs, name, label, locale, params);
+    }
+
+    /**
+     * Creates a navigator for a given model.
+     */
+    public Component createNavigator(HelpModel model) {
+	return new JHelpSearchNavigator(this, model);
+    }
+    
+
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/SecondaryWindow.java b/jhMaster/JavaHelp/src/new/javax/help/SecondaryWindow.java
new file mode 100644
index 0000000000000000000000000000000000000000..3b5c63f9a0e27bcb5094a2a54f1831a1a5b4f884
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/SecondaryWindow.java
@@ -0,0 +1,152 @@
+/*
+ * @(#)SecondaryWindow.java	1.5 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help;
+
+import java.util.Hashtable;
+
+/**
+ * MainWindowPresentation is a class that will create a single main help 
+ * window for an application. Although there is generally only one per
+ * application there can  be multiple MainWindowPresentation.
+ * By default it is a tri-paned fully decorated window
+ * consisting of a toolbar, navigator pane, and help content view. By default
+ * the class is not destroyed when the window exits.
+ *
+ * @author Roger D.Brinkley
+ * @version	1.5	10/30/06
+ * @since 2.0
+ *
+ * @see javax.help.WindowPresentation
+ * @see javax.help.Presentation
+ */
+
+public class SecondaryWindow extends WindowPresentation {
+
+    static private Hashtable windows = new Hashtable();
+    private String name;
+
+    private SecondaryWindow(HelpSet hs, String name) {
+	super(hs);
+	this.name = name;
+    }
+
+    /**
+     * Get a named SecondaryWindow for a given HelpSet.
+     * Named SecondaryWindows are stored. If a named 
+     * SecondaryWindow exits then it is returned, otherwise a new
+     * secondary window is created. If there is a HelpSet.Presentation of the
+     * same name the presentation attibutes will be used, otherwise, the 
+     * default HelpSet.Presentation is used.
+     * 
+     * @param hs The HelpSet used in this presentation
+     * @param name The name of the Presentation to create - also the name
+     *             of the HelpSet.Presentation to use.
+     * @returns Presentation A unique MainWindowPresentation. 
+     */
+    static public Presentation getPresentation(HelpSet hs, String name) {
+	debug ("getPresentation");
+	SecondaryWindow swp;
+
+	String winName = name;
+	if (name == null) {
+	    winName = "";
+	}
+
+	// Use the secondary window if one exists
+	swp = (SecondaryWindow) windows.get(winName);
+	if (swp != null) {
+	    if (swp.getHelpSet() != hs) {
+		swp.setHelpSet(hs);
+	    }
+	    return swp;
+	}
+
+	debug ("no Presentation - start again");
+	swp = new SecondaryWindow(hs, winName);
+
+	// Set the SecondaryWindow defaults
+	swp.setViewDisplayed(false);
+	swp.setToolbarDisplayed(false);
+	swp.setDestroyOnExit(true);
+	swp.setTitleFromDocument(true);
+
+	if (hs != null) {
+	    HelpSet.Presentation presentation = null;
+
+	    // get a named presentation if one exists
+	    if (name != null) {
+		presentation = hs.getPresentation(name);
+	    }
+
+	    // get the default presentation if one exits
+	    if (presentation == null) {
+		presentation = hs.getDefaultPresentation();
+	    }
+
+	    // set the presentation
+	    // a null is ok here as it will just return.
+	    swp.setHelpSetPresentation(presentation);
+
+	    windows.put(winName, swp);
+	}
+	return swp;
+    }
+
+    /**
+     * Gets a SecondaryWindow if one exists. Does not 
+     * create a Presentation if one does not exist.
+     * 
+     * @param name Name of the presentation to get
+     * @return SecondaryWindow The found Presentation or null
+     */
+    static public SecondaryWindow getPresentation(String name) {
+	debug ("getPresenation(name)");
+	return (SecondaryWindow) windows.get(name);
+    }
+
+    /**
+     * Destroy the SecondaryWindowPresentatin. Specifically remove it from
+     * the list of SecondaryWindows.
+     */
+    public void destroy() {
+	super.destroy();
+	windows.remove(name);
+    }
+
+    /**
+     * Debugging code...
+     */
+
+    private static final boolean debug = false;
+    private static void debug(Object msg) {
+	if (debug) {
+	    System.err.println("SecondaryWindow: "+msg);
+	}
+    }
+ 
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/SeparatorAction.java b/jhMaster/JavaHelp/src/new/javax/help/SeparatorAction.java
new file mode 100644
index 0000000000000000000000000000000000000000..6e5ce0d0e44c26e76fd7ff55833f0b06d38feb86
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/SeparatorAction.java
@@ -0,0 +1,47 @@
+/*
+ * @(#)SeparatorAction.java	1.2 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.help.*;
+import javax.help.event.*;
+import java.util.Enumeration;
+import java.util.Stack;
+import javax.swing.*;
+
+/**
+ *
+ * @author Stepan Marek
+ * @version	1.2	10/30/06
+ */
+public class SeparatorAction extends AbstractHelpAction {
+    public SeparatorAction(Object control) {
+        super(control, "SeparatorAction");
+    }
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/ServletHelpBroker.java b/jhMaster/JavaHelp/src/new/javax/help/ServletHelpBroker.java
new file mode 100644
index 0000000000000000000000000000000000000000..c882a24343428adf19163ab67d3fb45edee07137
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/ServletHelpBroker.java
@@ -0,0 +1,400 @@
+/*
+ * @(#)ServletHelpBroker.java	1.3 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+package javax.help;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.net.URL;
+import java.net.MalformedURLException;
+import java.awt.*;
+import java.awt.event.*;
+import javax.help.Map.ID;
+import java.util.Locale;
+import java.awt.Font;
+import java.awt.Dimension;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.jsp.JspWriter;
+import javax.swing.tree.DefaultMutableTreeNode;
+import java.io.IOException;
+
+/**
+ * An implmentation of the HelpBroker interface for Servlets
+ *
+ * @author Roger Brinkley
+ * @version	1.3	10/30/06
+ */
+
+public class ServletHelpBroker implements HelpBroker {
+
+    protected HelpSet helpset = null;
+    protected DefaultHelpModel model = null;
+    protected NavigatorView curNav = null;
+    protected boolean viewDisplayed = true;
+    protected Locale locale=null;
+    protected Font font;
+
+    /**
+     * Zero-argument constructor.
+     * It should be followed by a setHelpSet() invocation.
+     */
+
+    public ServletHelpBroker() {
+    }
+
+    /**
+     * Returns the default HelpSet
+     */
+    public HelpSet getHelpSet() {
+	return helpset;
+    }
+
+    /**
+     * Changes the HelpSet for this broker.
+     * @param hs The HelpSet to set for this broker. 
+     * A null hs is valid parameter.
+     */
+    public void setHelpSet(HelpSet hs) {
+	if (hs != null && helpset != hs) {
+	    model = new DefaultHelpModel(hs);
+	    helpset = hs;
+	}
+    }
+
+
+    /**
+     * Gets the locale of this component.
+     * @return This component's locale. If this component does not
+     * have a locale, the defaultLocale is returned.
+     * @see #setLocale
+     */
+    public Locale getLocale() {
+	if (locale == null) {
+	  return Locale.getDefault();
+	}
+	return locale;
+    }
+
+    /**
+     * Sets the locale of this HelpBroker. The locale is propagated to
+     * the presentation.
+     * @param l The locale to become this component's locale. A null locale
+     * is the same as the defaultLocale.
+     * @see #getLocale
+     */
+    public void setLocale(Locale l) {
+	locale = l;
+    }
+
+    /**
+     * Gets the font for this HelpBroker.
+     */
+    public Font getFont () {
+	return font;
+    }
+
+    /**
+     * Sets the font for this this HelpBroker.
+     * @param f The font.
+     */
+    public void setFont (Font f) {
+	font = f;
+    }
+
+    /**
+     * Set the currentView to the navigator with the same 
+     * name as the <tt>name</tt> parameter.
+     *
+     * @param name The name of the navigator to set as the 
+     * current view. If nav is null or not a valid Navigator 
+     * in this HelpBroker then an 
+     * IllegalArgumentException is thrown.
+     * @throws IllegalArgumentException if nav is null or not a valid Navigator.
+     */
+    public void setCurrentView(String name) {
+
+	NavigatorView views[] = helpset.getNavigatorViews();
+	for (int i=0; i<views.length; i++) {
+	    if (views[i].getName().equals(name)) {
+		curNav = views[i];
+		return;
+	    }
+	}
+	// did find a suitable navigator
+	throw new IllegalArgumentException("Invalid view name");
+    }
+
+    /**
+     * Determines the current navigator.
+     */
+    public String getCurrentView() {
+	// if the current Nav isn't set then use the first Nav from the
+	// the helpset.
+	if (curNav == null) {
+	    if (helpset != null) {
+		NavigatorView views[] = helpset.getNavigatorViews();
+		curNav = views[0];
+	    } else {
+		// Argh! there werent' any navigators in the helpset 
+		// return null;
+		return null;
+	    }
+	}	
+	return curNav.getName();
+    }
+
+
+    /**
+     * Returns the current navigator as a NavigatorView.
+     */
+    public NavigatorView getCurrentNavigatorView() {
+	// if the current Nav isn't set then use the first Nav from the
+	// the helpset.
+	if (curNav == null) {
+	    if (helpset != null) {
+		NavigatorView views[] = helpset.getNavigatorViews();
+		curNav = views[0];
+	    } else {
+		// Argh! there werent' any navigators in the helpset 
+		// return null;
+		return null;
+	    }
+	}	
+	return curNav;
+    }
+
+
+    /**
+     * Initializes the presentation.
+     * Not implemented in ServletHelpBroker.
+     */
+    public void initPresentation() {
+    }
+
+    /**
+     * Displays the presentation to the user.
+     */
+    public void setDisplayed(boolean b) {
+	// ignore this is always displayed
+    }
+
+    /**
+     * Determines if the presentation is displayed.
+     */
+    public boolean isDisplayed() {
+	return true;
+    }
+
+    /**
+     * Requests the presentation be located at a given position.
+     * This operation throws an UnsupportedOperationException
+     * in ServletHelpBroker
+     */
+    public void setLocation(Point p) throws javax.help.UnsupportedOperationException {
+	throw new javax.help.UnsupportedOperationException("Not implemented in ServeltHelpBroker");
+    }
+
+    /**
+     * Requests the location of the presentation.
+     * This operation throws an UnsupportedOperationException
+     * in ServletHelpBroker
+     */
+    public Point getLocation() throws javax.help.UnsupportedOperationException {
+	throw new javax.help.UnsupportedOperationException("Not implemented in ServeltHelpBroker");
+    }
+
+    /**
+     * Requests the presentation be set to a given size.
+     * This operation throws an UnsupportedOperationException
+     * in ServletHelpBroker
+     */
+    public void setSize(Dimension d) throws javax.help.UnsupportedOperationException {
+	throw new javax.help.UnsupportedOperationException("Not implemented in ServeltHelpBroker");
+    }
+
+    /**
+     * Requests the size of the presentation.
+     * throws UnsupportedOperationException in ServletHelpBroker.
+     */
+    public Dimension getSize() throws javax.help.UnsupportedOperationException {
+	throw new javax.help.UnsupportedOperationException("Not implemented in ServeltHelpBroker");
+    }
+
+    /**
+     * Requests the presentation be set to a given screen.
+     * This operation throws an UnsupportedOperationException
+     * in ServletHelpBroker
+     */
+    public void setScreen(int screen) throws javax.help.UnsupportedOperationException {
+	throw new javax.help.UnsupportedOperationException("Not implemented in ServeltHelpBroker");
+    }
+
+    /**
+     * Requests the screen of the presentation.
+     * throws UnsupportedOperationException in ServletHelpBroker.
+     */
+    public int getScreen() throws javax.help.UnsupportedOperationException {
+	throw new javax.help.UnsupportedOperationException("Not implemented in ServeltHelpBroker");
+    }
+
+    /**
+     * Hides/Shows view.
+     */
+    public void setViewDisplayed(boolean displayed) {
+	viewDisplayed = displayed;
+    }
+
+    /**
+     * Determines if the current view is visible.
+     */
+    public boolean isViewDisplayed() {
+	return viewDisplayed;
+    }
+
+    /**
+     * Shows this ID as content relative to the (top) HelpSet for the HelpBroker
+     * instance--HelpVisitListeners are notified.
+     *
+     * @param id A string that identifies the topic to show for the loaded (top) HelpSet
+     * @exception BadIDException The ID is not valid for the HelpSet
+     */
+    public void setCurrentID(String id) throws BadIDException {
+	try {
+	    setCurrentID(ID.create(id, helpset));
+	} catch (InvalidHelpSetContextException ex) {
+	    // this should not happen
+	    new Error("internal error?");
+	}
+    }
+
+    /**
+     * Displays this ID--HelpVisitListeners are notified.
+     *
+     * @param id a Map.ID indicating the URL to display
+     * @exception InvalidHelpSetContextException if the current helpset does not contain
+     * id.helpset
+     */
+    public void setCurrentID(ID id) throws InvalidHelpSetContextException {
+	debug("setCurrentID");
+
+	model.setCurrentID(id);
+    }
+
+    /**
+     * Determines which ID is displayed (if any).
+     */
+    public ID getCurrentID() {
+	return model.getCurrentID();
+    }
+
+    /**
+     * Displays this URL.
+     * HelpVisitListeners are notified.
+     * The currentID changes if there is a mathing ID for this URL
+     * @param url The url to display. A null URL is a valid url.
+     */
+    public void setCurrentURL(URL url) {
+	model.setCurrentURL(url);
+    }
+
+    /**
+     * Determines which URL is displayed.
+     */
+    public URL getCurrentURL() {
+	return model.getCurrentURL();
+    }
+
+
+    // Context-Senstive methods
+    /**
+     * Enables the Help key on a Component. 
+     * Not implemented in ServletHelpBroker
+     */
+    public void enableHelpKey(Component comp, String id, HelpSet hs) {
+    }
+
+    /**
+     * Enables help for a Component. 
+     * Not implemented in ServletHelpBroker
+     */
+    public void enableHelp(Component comp, String id, HelpSet hs) 
+    {
+    }
+
+    /**
+     * Enables help for a MenuItem. 
+     * Not implemented in ServletHelpBroker
+     */
+    public void enableHelp(MenuItem comp, String id, HelpSet hs) 
+    {
+    }
+
+    /**
+     * Enables help for a Component.
+     * Not implemented in ServletHelpBroker
+     */
+    public void enableHelpOnButton(Component comp, String id, HelpSet hs) 
+    {
+    }
+
+    /**
+     * Enables help for a MenuItem.
+     * Not implemented in ServletHelpBroker.
+     */
+    public void enableHelpOnButton(MenuItem comp, String id, HelpSet hs) 
+    {
+    }
+
+    // Investigate if the following need to be implemented
+    public void setHelpSetPresentation(HelpSet.Presentation pres) {
+    }
+    public void showID(String id, String presentation, 
+		       String presentationName) throws BadIDException {
+    }
+    public void showID(ID id, String presentation, String presentationName) 
+	throws InvalidHelpSetContextException {
+    }
+    public void enableHelpKey(Component comp, String id, HelpSet hs,
+			      String presentation, String presentationName) {
+    }
+    public void enableHelpOnButton(Object obj, String id, HelpSet hs,
+				   String presentation, 
+				   String presentationName) 
+    {
+    }
+    /**
+     * Debugging code...
+     */
+
+    private static final boolean debug = false;
+    private static void debug(Object msg) {
+	if (debug) {
+	    System.err.println("ServletHelpBroker: "+msg);
+	}
+    }
+ 
+}
+
diff --git a/jhMaster/JavaHelp/src/new/javax/help/SortMerge.java b/jhMaster/JavaHelp/src/new/javax/help/SortMerge.java
new file mode 100644
index 0000000000000000000000000000000000000000..48d836c1083e4c025e53342983024810813ddeb2
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/SortMerge.java
@@ -0,0 +1,254 @@
+/*
+ * @(#)SortMerge.java	1.12 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help;
+
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.TreeNode;
+import java.util.*;
+import java.text.*;
+
+/**
+ * Sort merge type
+ *
+ * @author Richard Gregor
+ * @version	1.12	10/30/06
+ */
+public class SortMerge extends Merge{
+
+    /**
+     * Constructs SortMerge
+     *
+     * @param master The master NavigatorView
+     * @param slave The slave NavigatorView
+     */
+    public SortMerge(NavigatorView master, NavigatorView slave) {
+        super(master,slave);
+    }
+    
+    /**
+     * Processes sort merge 
+     *
+     * @param node The master node (This node must be sorted)
+     * @return Merged master node
+     */
+    public TreeNode processMerge(TreeNode node) {
+	debug("processMerge started");
+        DefaultMutableTreeNode masterNode = (DefaultMutableTreeNode) node;
+        
+        //if master and slave are the same object return the
+	// masterNode 
+        if (masterNode.equals(slaveTopNode)) {
+            return masterNode;
+        }
+        
+	// If there are no children in slaveTopNode return the
+	// masterNode
+        if (slaveTopNode.getChildCount() == 0) { 
+            return masterNode;
+        }
+        
+	// If there are no children in the masterNode process the slaveTopNode
+	// and return the slaveTopNode
+	if (masterNode.getChildCount() == 0) {
+	    MergeHelpUtilities.mergeNodeChildren("javax.help.SortMerge",
+						 slaveTopNode);
+	    // It would be better to return the slaveNode but that causes 
+	    // problems in the UIs so return the masterNode after adding
+	    // all the slavNodes
+	    while (slaveTopNode.getChildCount() > 0) {
+		masterNode.add((DefaultMutableTreeNode) slaveTopNode.getFirstChild());
+	    }
+	    return masterNode;
+	}
+
+	mergeNodes(masterNode, slaveTopNode);
+	debug("process merge ended");
+        return masterNode;
+    }
+
+    /**
+     * Merge Nodes. Merge two nodes according to the Sort merging rules 
+     *
+     * @param masterNode The master node to merge with 
+     * @param slaveNode The node to merge into the master
+     */
+    public static void mergeNodes(TreeNode master, TreeNode slave) {
+	debug("mergeNodes started");
+	DefaultMutableTreeNode masterNode = (DefaultMutableTreeNode)master;
+	DefaultMutableTreeNode slaveNode = (DefaultMutableTreeNode)slave;
+
+	// It is important that the masterNode already be sorted
+	sortNode(slaveNode, MergeHelpUtilities.getLocale(slaveNode));
+	int masterCnt = masterNode.getChildCount();
+	int m = 0;
+	DefaultMutableTreeNode masterAtM=null;
+	
+	if (masterCnt > 0) {
+	    masterAtM = (DefaultMutableTreeNode)masterNode.getChildAt(m);
+	}
+
+	DefaultMutableTreeNode slaveNodeChild = null;
+	
+	//Loop through the slaves
+	while (slaveNode.getChildCount() > 0 && masterAtM != null) {
+	    slaveNodeChild = (DefaultMutableTreeNode)slaveNode.getFirstChild();
+	    
+	    // compare this slaveChild to the masterChild
+	    int compareVal = MergeHelpUtilities.compareNames(masterAtM,
+							     slaveNodeChild);
+	    
+	    // if < 0 get the next master child
+	    if (compareVal < 0 ) {
+		++m;
+		// break out if we've done all we can do.
+		if (m >= masterCnt) {
+		    break;
+		}
+		masterAtM = (DefaultMutableTreeNode)masterNode.getChildAt(m);
+		continue;
+	    } else if (compareVal > 0) {
+		// slaveNodeChild is lexically procedes the masterNodeChild
+		// add the slaveNodeChild and merge in the node children
+		// and then continue. You automatically get the next 
+		// slaveNodeChild
+		masterNode.add(slaveNodeChild);
+		MergeHelpUtilities.mergeNodeChildren("javax.help.SortMerge",
+						     slaveNodeChild);
+		continue;
+	    } else {
+		// The masterChild and slaveChild are equal
+		if (MergeHelpUtilities.haveEqualID(masterAtM, slaveNodeChild)) {
+
+		    // Merge the masterchild and slaveNodeChild together
+		    // based on the mergetype of the masterChild
+		    MergeHelpUtilities.mergeNodes("javax.help.SortMerge",
+						  masterAtM, slaveNodeChild);
+		    
+		    // Need to remove the slaveNodeChild from the list
+		    slaveNodeChild.removeFromParent();
+		    slaveNodeChild = null;
+		} else {
+		    // Names are the same but the ID are not
+		    // Mark the nodes and add the slaveChild
+		    MergeHelpUtilities.markNodes(masterAtM, slaveNodeChild);
+		    masterNode.add(slaveNodeChild);
+		    MergeHelpUtilities.mergeNodeChildren("javax.help.SortMerge",
+							 slaveNodeChild);
+		}
+	    }
+	}
+
+	// Add the remainong slave node children
+	while (slaveNode.getChildCount() > 0) {
+	    slaveNodeChild = (DefaultMutableTreeNode)slaveNode.getFirstChild();
+	    masterNode.add(slaveNodeChild);
+	    MergeHelpUtilities.mergeNodeChildren("javax.help.SortMerge",
+						 slaveNodeChild);
+	}
+
+	// ok make sure the masterNode is sorted
+	mergeNodeChildren(masterNode);
+	debug ("mergeNode ended");
+    }
+
+
+    /**
+     * Merge Node Children. Merge the children of a node according to the
+     * Sort merging rules.
+     *
+     * @param node The parent node from which the children are merged
+     */
+    public static void mergeNodeChildren(TreeNode node) {
+	DefaultMutableTreeNode masterNode = (DefaultMutableTreeNode)node;
+	debug("mergeNodeChildren master=" + MergeHelpUtilities.getNodeName(masterNode));
+
+	// Sort the children
+	sortNode(masterNode, MergeHelpUtilities.getLocale(masterNode));
+
+	// merge the children's children
+	for (int i=0; i < masterNode.getChildCount(); i++) {
+	    DefaultMutableTreeNode child = 
+		(DefaultMutableTreeNode)masterNode.getChildAt(i);
+	    if (!child.isLeaf()) {
+		MergeHelpUtilities.mergeNodeChildren("javax.help.SortMerge",
+						     child);
+	    }
+	}
+    }
+
+    /**
+     * Sorts children of node using Array.sort 
+     *
+     * @param node The node to sort
+     * @param locale The locale
+     * @return Sorted node
+     */ 
+    public static void sortNode(DefaultMutableTreeNode node, Locale locale) {
+	debug ("sortNode");
+        if (locale == null) {
+            locale = Locale.getDefault();
+	}
+        
+	//Locale locale = MergeHelpUtilities.getLocale(node);         
+	CollationKey temp;
+	int size = node.getChildCount();
+	DefaultMutableTreeNode sortedNode = new DefaultMutableTreeNode();
+	
+	Collator collator = Collator.getInstance(locale);
+	CollationKey[] keys = new CollationKey[size];
+	
+	for (int i = 0; i < size; i++) {
+	    String string = MergeHelpUtilities.getNodeName((DefaultMutableTreeNode)node.getChildAt(i));
+	    debug("String , i:"+string+" , "+i);
+	    keys[i] = collator.getCollationKey(string);
+	}
+	
+	Arrays.sort(keys);
+	
+	for (int i = 0; i < size; i++) {
+	    DefaultMutableTreeNode child = MergeHelpUtilities.getChildWithName(node,keys[i].getSourceString()); 
+	    if (child != null) {
+		sortedNode.add(child);
+	    }
+	}
+            
+	while (sortedNode.getChildCount() > 0) {
+	    node.add((DefaultMutableTreeNode) sortedNode.getFirstChild());
+	}
+        
+	debug ("end sortNode");
+    }
+    
+  
+    private static boolean debug = false;
+    private static void debug(String msg) {
+        if (debug) {
+            System.out.println("SortMerge :"+msg);
+	}
+    }
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/SwingHelpUtilities.java b/jhMaster/JavaHelp/src/new/javax/help/SwingHelpUtilities.java
new file mode 100644
index 0000000000000000000000000000000000000000..252c0ea55d84756de704d0ae6618472971996a8a
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/SwingHelpUtilities.java
@@ -0,0 +1,395 @@
+/*
+ * @(#)SwingHelpUtilities.java	1.10 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help;
+
+import java.io.BufferedInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.io.IOException;
+import java.lang.reflect.Method;
+import javax.swing.ImageIcon;
+import javax.swing.JComponent;
+import javax.swing.UIManager;
+import javax.swing.LookAndFeel;
+import javax.swing.UIDefaults;
+import javax.swing.plaf.ComponentUI;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+
+/**
+ * Provides a number of utility functions:
+ *
+ * Support for Beans, mapping from a Bean class to its HelpSet and to
+ * its ID.
+ * Support for LAF changes.
+ * Support for finding localized resources.
+ *
+ * This class has no public constructor.
+ *
+ * @author Eduardo Pelegri-Llopart
+ * @author Roger D. Brinkley
+ * @version	1.10	10/30/06
+ */
+
+public class SwingHelpUtilities implements PropertyChangeListener {
+
+    private static UIDefaults uiDefaults = null;
+    private static SwingHelpUtilities myLAFListener = new SwingHelpUtilities();
+    private static String contentViewerUI = null;
+
+    static {
+        installUIDefaults();
+    }
+    
+    //=========
+    /**
+     * LAF support
+     */
+
+    /**
+     * The PropertyChange method is used to track changes to LookAndFeel
+     * via the "lookAndFeel" property.
+     */
+
+    public void propertyChange(PropertyChangeEvent event) {
+	String changeName = event.getPropertyName();
+	if (changeName.equals("lookAndFeel")) {
+	    installLookAndFeelDefaults();
+        }
+    }
+
+    /**
+     * Installs UIDefaults for Help components and installs "lookAndFeel"
+     * property change listener.
+     */
+    static void installUIDefaults() {
+        UIDefaults table = UIManager.getLookAndFeelDefaults();
+        if (uiDefaults != table) {
+            uiDefaults = table;
+            UIManager.removePropertyChangeListener(myLAFListener);
+            installLookAndFeelDefaults();
+            UIManager.addPropertyChangeListener(myLAFListener);
+        }
+    }
+
+    /**
+     * Set the default ContentViewerUI
+     * 
+     * param cvUI - full class name of the content viewer UI
+     */
+    public static void setContentViewerUI(String cvUI) {
+	if (cvUI != null) {
+	    try {
+		Class c = Class.forName(cvUI);
+		// an error will be thrown if the class doesn't exist
+		contentViewerUI = cvUI;
+	    } catch (Throwable e) {
+		System.out.println("ContentViewerClass " + cvUI + " doesn't exist");
+	    }
+	}
+    }
+
+    /**
+     * Adds look and feel constants for Help components into UIDefaults table.
+     */
+    static void installLookAndFeelDefaults() {
+        LookAndFeel lnf = UIManager.getLookAndFeel();
+        UIDefaults table = UIManager.getLookAndFeelDefaults();
+
+	debug("installLookAndFeelDefaults - " + lnf);
+
+        if ((lnf != null) && (table != null)) {
+	    if (lnf.getID().equals("Motif")) {
+		installMotifDefaults(table);
+	    } else if (lnf.getID().equals("Windows")) {
+		installWindowsDefaults(table);
+	    } else if (lnf.getID().equals("GTK")) {
+		installGTKDefaults(table);
+	    } else {
+		// Default
+		installMetalDefaults(table);
+	    }
+	}
+	debug ("verifing UIDefaults; HelpUI=" + table.getString("HelpUI"));
+
+    }
+
+    /**
+     * Dynamically invoke a cursor factory to get a cursor.
+     */
+    private static Object createIcon(String factoryName,
+				     String method) {
+	ClassLoader loader = HelpUtilities.class.getClassLoader();
+	try {
+	    Class types[] = new Class[0];
+	    Object args[] = new Object[0];
+	    Class klass;
+
+	    if (loader == null) {
+		klass = Class.forName(factoryName);
+	    } else {
+		klass = loader.loadClass(factoryName);
+	    }
+	    Method m = klass.getMethod(method, types);
+	    Object back = m.invoke(null, args);
+	    return back;
+	} catch (Exception ex) {
+	    return null;
+	}
+    }
+
+    static Object basicOnItemCursor = new UIDefaults.LazyValue() {
+	public Object createValue(UIDefaults table) {
+	    return createIcon("javax.help.plaf.basic.BasicCursorFactory",
+			      "getOnItemCursor");
+	}
+    };
+
+    static Object basicDnDCursor = new UIDefaults.LazyValue() {
+        public Object createValue(UIDefaults table) {
+	    return createIcon("javax.help.plaf.basic.BasicCursorFactory",
+			      "getDnDCursor");
+	}
+    };
+
+    static Object gtkOnItemCursor = new UIDefaults.LazyValue() {
+	public Object createValue(UIDefaults table) {
+	    return createIcon("javax.help.plaf.gtk.GTKCursorFactory",
+			      "getOnItemCursor");
+	}
+    };
+
+    static Object gtkDnDCursor = new UIDefaults.LazyValue() {
+        public Object createValue(UIDefaults table) {
+	    return createIcon("javax.help.plaf.gtk.GTKCursorFactory",
+			      "getDnDCursor");
+	}
+    };
+
+
+    /*
+     * Utility method that creates a UIDefaults.LazyValue that creates
+     * an ImageIcon for the specified <code>image</code>
+     * filename. I tried to use the similar LookAndFeel.makeIcon() method but it
+     * creates IconUIResource instaed of Icon Image and buttons cannot then produce
+     * disabled icon from it.
+     */
+    static private Object makeBasicIcon(final String image) {
+        return new UIDefaults.LazyValue() {
+            public Object createValue(UIDefaults table) {
+                return SwingHelpUtilities.getImageIcon(javax.help.plaf.basic.BasicHelpUI.class, image);
+            }
+        };
+    }
+
+    /**
+     * The basic LAF does what we need.
+     */
+    static private void installBasicDefaults(UIDefaults table) {
+
+        String basicPackageName = "javax.help.plaf.basic.";
+
+	String basicContentViewerUI = basicPackageName + "BasicContentViewerUI";
+	if (contentViewerUI != null) {
+	    basicContentViewerUI = contentViewerUI;
+	}
+
+	Object[] uiDefaults = {
+	                "HelpUI", basicPackageName + "BasicHelpUI",
+	    "HelpTOCNavigatorUI", basicPackageName + "BasicTOCNavigatorUI",
+	  "HelpIndexNavigatorUI", basicPackageName + "BasicIndexNavigatorUI",
+	 "HelpSearchNavigatorUI", basicPackageName + "BasicSearchNavigatorUI",
+       "HelpGlossaryNavigatorUI", basicPackageName + "BasicGlossaryNavigatorUI",
+      "HelpFavoritesNavigatorUI", basicPackageName + "BasicFavoritesNavigatorUI",
+	   "HelpContentViewerUI", basicContentViewerUI,
+                 "HelpDnDCursor", basicDnDCursor,
+	      "HelpOnItemCursor", basicOnItemCursor,
+               "BackAction.icon", makeBasicIcon("images/Back.gif"),
+            "ForwardAction.icon", makeBasicIcon("images/Forward.gif"),
+              "PrintAction.icon", makeBasicIcon("images/Print.gif"),
+         "PrintSetupAction.icon", makeBasicIcon("images/PrintSetup.gif"),
+             "ReloadAction.icon", makeBasicIcon("images/Reload.gif"),
+          "FavoritesAction.icon", makeBasicIcon("images/Favorites.gif"),
+               "HomeAction.icon", makeBasicIcon("images/Home.gif"),
+      	     "FavoritesNav.icon", makeBasicIcon("images/FavoritesNav.gif"),
+                 "IndexNav.icon", makeBasicIcon("images/IndexNav.gif"),
+                   "TOCNav.icon", makeBasicIcon("images/TOCNav.gif"),
+                "SearchNav.icon", makeBasicIcon("images/SearchNav.gif"),
+              "GlossaryNav.icon", makeBasicIcon("images/GlossaryNav.gif"),
+               "HistoryNav.icon", makeBasicIcon("images/HistoryNav.gif"),
+                "SearchLow.icon", makeBasicIcon("images/SearchLow.gif"),
+             "SearchMedLow.icon", makeBasicIcon("images/SearchMedLow.gif"),
+                "SearchMed.icon", makeBasicIcon("images/SearchMed.gif"),
+            "SearchMedHigh.icon", makeBasicIcon("images/SearchMedHigh.gif"),
+               "SearchHigh.icon", makeBasicIcon("images/SearchHigh.gif")
+	};
+
+	table.putDefaults(uiDefaults);
+    }
+
+    /**
+     * If we had any LAF-specific classes, they would be invoked from here.
+     */
+    static private void installMetalDefaults(UIDefaults table) {
+	installBasicDefaults(table);
+    }
+
+    static private void installWindowsDefaults(UIDefaults table) {
+	installBasicDefaults(table);
+    }
+
+    static private void installMotifDefaults(UIDefaults table) {
+	installBasicDefaults(table);
+    }
+
+    /*
+     * Utility method that creates a UIDefaults.LazyValue that creates
+     * an ImageIcon for the specified <code>image</code>
+     * filename. I tried to use the similar LookAndFeel.makeIcon() method but it
+     * creates IconUIResource instaed of Icon Image and buttons cannot then produce
+     * disabled icon from it.
+     */
+    static private Object makeGTKIcon(final String image) {
+        return new UIDefaults.LazyValue() {
+            public Object createValue(UIDefaults table) {
+                return SwingHelpUtilities.getImageIcon(javax.help.plaf.gtk.GTKCursorFactory.class, 
+						       image);
+            }
+        };
+    }
+
+    static private void installGTKDefaults(UIDefaults table) {
+        String basicPackageName = "javax.help.plaf.basic.";
+	String gtkPackageName = "javax.help.plaf.gtk.";
+
+	String basicContentViewerUI = basicPackageName + "BasicContentViewerUI";
+	if (contentViewerUI != null) {
+	    basicContentViewerUI = contentViewerUI;
+	}
+
+	Object[] uiDefaults = {
+	                "HelpUI", basicPackageName + "BasicHelpUI",
+	    "HelpTOCNavigatorUI", basicPackageName + "BasicTOCNavigatorUI",
+	  "HelpIndexNavigatorUI", basicPackageName + "BasicIndexNavigatorUI",
+	 "HelpSearchNavigatorUI", basicPackageName + "BasicSearchNavigatorUI",
+       "HelpGlossaryNavigatorUI", basicPackageName + "BasicGlossaryNavigatorUI",
+      "HelpFavoritesNavigatorUI", basicPackageName + "BasicFavoritesNavigatorUI",
+	   "HelpContentViewerUI", basicContentViewerUI,
+                 "HelpDnDCursor", gtkDnDCursor,
+	      "HelpOnItemCursor", gtkOnItemCursor,
+               "BackAction.icon", makeGTKIcon("images/Back.png"),
+            "ForwardAction.icon", makeGTKIcon("images/Forward.png"),
+              "PrintAction.icon", makeGTKIcon("images/Print.png"),
+         "PrintSetupAction.icon", makeGTKIcon("images/PrintSetup.png"),
+             "ReloadAction.icon", makeGTKIcon("images/Reload.png"),
+          "FavoritesAction.icon", makeGTKIcon("images/Favorites.png"),
+               "HomeAction.icon", makeGTKIcon("images/Home.png"),
+      	     "FavoritesNav.icon", makeGTKIcon("images/FavoritesNav.png"),
+                 "IndexNav.icon", makeGTKIcon("images/IndexNav.gif"),
+                   "TOCNav.icon", makeGTKIcon("images/TOCNav.gif"),
+                "SearchNav.icon", makeGTKIcon("images/SearchNav.gif"),
+              "GlossaryNav.icon", makeGTKIcon("images/GlossaryNav.gif"),
+               "HistoryNav.icon", makeGTKIcon("images/HistoryNav.gif"),
+                "SearchLow.icon", makeGTKIcon("images/SearchLow.gif"),
+             "SearchMedLow.icon", makeGTKIcon("images/SearchMedLow.gif"),
+                "SearchMed.icon", makeGTKIcon("images/SearchMed.gif"),
+            "SearchMedHigh.icon", makeGTKIcon("images/SearchMedHigh.gif"),
+               "SearchHigh.icon", makeGTKIcon("images/SearchHigh.gif")
+	};
+
+	table.putDefaults(uiDefaults);
+    }
+
+    /**
+     * Create an Icon from a given resource.
+     * 
+     * This works uisng getResourceAsStream() because several browsers do not
+     * correctly implement getResource().
+     *
+     * This method may change...
+     */
+
+    public static ImageIcon getImageIcon(final Class baseClass,
+					 final String image) {
+	if (image == null) {
+	    return null;
+	}
+	final byte[][] buffer = new byte[1][];
+	try {
+	    InputStream resource = baseClass.getResourceAsStream(image);
+	    if (resource == null) {
+		return null; 
+	    }
+	    BufferedInputStream in = new BufferedInputStream(resource);
+	    ByteArrayOutputStream out = new ByteArrayOutputStream(1024);
+	    buffer[0] = new byte[1024];
+	    int n;
+	    while ((n = in.read(buffer[0])) > 0) {
+		out.write(buffer[0], 0, n);
+	    }
+	    in.close();
+	    out.flush();
+	    buffer[0] = out.toByteArray();
+	} catch (IOException ioe) {
+	    System.err.println(ioe.toString());
+	    return null;
+	}
+	if (buffer[0] == null) {
+	    System.err.println(baseClass.getName() + "/" + 
+			       image + " not found.");
+	    return null;
+	}
+	if (buffer[0].length == 0) {
+	    System.err.println("warning: " + image + 
+			       " is zero-length");
+	    return null;
+	}
+	
+	return new ImageIcon(buffer[0]);
+    }
+
+    static void addPropertyChangeListener(Object object, PropertyChangeListener listener) {
+        try {
+            Class types[] = { PropertyChangeListener.class };
+            Object args[] = { listener };
+            object.getClass().getMethod("addPropertyChangeListener", types).invoke(object, args);
+        } catch (Exception ex) {
+        }
+    }
+
+    /**
+     * Debug support
+     */
+
+    private static final boolean debug = false;
+    private static void debug(Object msg1) {
+	if (debug) {
+	    System.err.println("GUIHelpUtilities: "+msg1);
+	}
+    }
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/TOCItem.java b/jhMaster/JavaHelp/src/new/javax/help/TOCItem.java
new file mode 100644
index 0000000000000000000000000000000000000000..e478dc854424989f98aa5bfef029166d748cdb11
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/TOCItem.java
@@ -0,0 +1,92 @@
+/*
+ * @(#)TOCItem.java	1.17 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help;
+
+import javax.help.Map.ID;
+import java.util.Locale;
+
+/**
+ * A class for individual TOC items
+ *
+ * @author Roger D. Brinkley
+ * @author Eduardo Pelegri-llopart
+ * @(#)TOCItem.java 1.13 01/29/99
+ */
+
+public class TOCItem extends TreeItem { 
+    private ID imageID;
+
+    /**
+     * Creates a TOCItem.
+     *
+     * @param id ID for the item. A null ID is valid.
+     * @param image The ID for image to be displayed for this item. A null
+     * image is valid.
+     * @param hs The HelpSet scoping this item.  In almost all cases
+     * this is the same as the HelpSet of the id field. A null ID is valid.
+     * @param lang The locale for this item. A null locale indicates the
+     * default locale.
+     */
+    public TOCItem(ID id, ID imageID, HelpSet hs, Locale locale) {
+	super(id, hs, locale);
+	this.imageID = imageID;
+    }
+
+    /**
+     * Creates a TOCItem with a default HelpSet based on its ID.
+     *
+     * @param id ID for the item. The ID can be null.
+     * @param image The image to be displayed for this item.
+     * @param lang The locale for this item
+     */
+    public TOCItem(ID id, ID imageID, Locale locale){
+	super(id, locale);
+	HelpSet hs = null;
+	if (id != null) {
+	    setHelpSet(id.hs);
+	}
+	this.imageID = imageID;
+    }
+
+    /**
+     * Creates a default TOCItem.
+     */
+
+    public TOCItem() {
+	super(null, null, null);
+	this.imageID = null;
+    }
+
+    /**
+     * Returns the image for this TOCItem.
+     */
+    public ID getImageID() {
+	 return imageID;
+    }
+
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/TOCView.java b/jhMaster/JavaHelp/src/new/javax/help/TOCView.java
new file mode 100644
index 0000000000000000000000000000000000000000..f61b5677483dd3ad66973a58a59a29f8694df25e
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/TOCView.java
@@ -0,0 +1,744 @@
+/*
+ * @(#)TOCView.java	1.37 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help;
+
+import java.awt.Component;
+import java.net.URL;
+import java.net.URLConnection;
+import java.io.Reader;
+import java.io.IOException;
+import java.util.Stack;
+import java.util.Hashtable;
+import java.util.Locale;
+import java.util.Vector;
+import java.util.Enumeration;
+import javax.help.Map.ID;
+import javax.swing.tree.TreeNode;
+import javax.swing.tree.DefaultMutableTreeNode;
+
+import com.sun.java.help.impl.*;
+
+/**
+ * Navigational View information for a TOC.
+ * This includes information about how to parse the data format.
+ *
+ * @author Eduardo Pelegri-Llopart
+ * @version	1.18	03/10/99
+ */
+
+public class TOCView extends NavigatorView {
+
+    /**
+     * PublicID (known to this XML processor) to the DTD for version 1.0 of the TOC.
+     */
+    public static final String publicIDString =
+        "-//Sun Microsystems Inc.//DTD JavaHelp TOC Version 1.0//EN";
+
+    /**
+     * PublicID (known to this XML processor) to the DTD for version 2.0 of the TOC.
+     */
+    public static final String publicIDString_V2 =
+        "-//Sun Microsystems Inc.//DTD JavaHelp TOC Version 2.0//EN";
+
+
+    private ID categoryOpenImageID = null;
+    private ID categoryClosedImageID = null;
+    private ID topicImageID = null;
+
+    /**
+     * Constructs a TOC VIew with some given data.  Locale defaults to that
+     * of the HelpSet.
+     *
+     * @param hs The HelpSet that provides context information.
+     * @param name The name of the View.
+     * @param label The label (to show the user) of the View.
+    * @param params A hashtable that provides different key/values for this type.
+    */
+    public TOCView(HelpSet hs,
+		   String name,
+		   String label,
+		   Hashtable params) {
+	this(hs, name, label, hs.getLocale(), params);
+    }
+
+    /**
+     * Constructs a TOC VIew with some given data.
+     *
+     * @param hs The HelpSet that provides context information.
+     * @param name The name of the View.
+     * @param label The label (to show the user) of the View.
+     * @param locale The default locale to interpret the data in this TOC.
+    * @param params A hashtable that provides different key/values for this type.
+    */
+    public TOCView(HelpSet hs,
+		   String name,
+		   String label,
+		   Locale locale,
+		   Hashtable params) {
+	super(hs, name, label, locale, params);
+    }
+
+    /**
+     * Creates a navigator for a given model.
+     */
+    public Component createNavigator(HelpModel model) {
+	return new JHelpTOCNavigator(this, model);
+    }
+    
+    /**
+     * Get the TOC navigators mergeType. Overrides getMergeType in NavigatorView
+     */
+    public String getMergeType() {
+	String mergeType = super.getMergeType();
+	if (mergeType == null) {
+	    return "javax.help.AppendMerge";
+	}
+	return mergeType;
+    }
+
+    // turn this on if you want messages on failures
+    private static boolean warningOfFailures = false;
+
+    /**
+     * Public method that gets a DefaultMutableTreeNode representing the information in this
+     * view instance.
+     * 
+     * The default implementation parses the data in the URL but a subclass may
+     * override this method and provide a different implemenation--for example,
+     * by creating the tree programatically.
+     */
+    public DefaultMutableTreeNode getDataAsTree() {
+	HelpSet hs = getHelpSet();
+	Hashtable params = getParameters();
+	URL url;
+
+	if (params == null || 
+	    (params != null && !params.containsKey("data"))) {
+	    DefaultMutableTreeNode node = new DefaultMutableTreeNode();
+	    return node;
+	}
+
+	try {
+	    url = new URL(hs.getHelpSetURL(), (String) params.get("data"));
+	} catch (Exception ex) {
+	    throw new Error("Trouble getting URL to TOC data; "+ex);
+	}
+
+	return parse(url, hs, hs.getLocale(), new DefaultTOCFactory(), this);
+    }
+
+    /**
+     * Public method for parsing a TOC in a URL.
+     * Returns a DefaultMutableTreeNode whose children are the DefaultMutableTreeNode
+     * corresponding to the tocitem's in the TOC.
+     * The factory is invoked to create the TreeItems that are included in the
+     * DefaultMutableTreeNode as user data.
+     * The factory is also invoked with start data, and whenever any parsing error
+     * is found.
+     *
+     * @param url Where the TOC lives. If null, returns a null value.
+     * @param hs The HelpSet context for this TOC. Null hs is ignored.
+     * @param locale The default locale to interpret the data in this TOC. Null locale 
+     * is treated as the default locale.
+     * @param factory A factory instance used to create the TOCItems.
+     * @return A TreeNode that represents the TOC. Returns null if parsing errors were
+     * encountered.
+     */
+    public static DefaultMutableTreeNode parse(URL url,
+					       HelpSet hs,
+					       Locale locale,
+					       TreeItemFactory factory) {
+	return parse(url, hs, locale, factory, null);
+    }
+
+    /**
+     * Public method for parsing a TOC in a URL.
+     * Returns a DefaultMutableTreeNode whose children are the DefaultMutableTreeNode
+     * corresponding to the tocitem's in the TOC.
+     * The factory is invoked to create the TreeItems that are included in the
+     * DefaultMutableTreeNode as user data.
+     * The factory is also invoked with start data, and whenever any parsing error
+     * is found.
+     *
+     * @param url Where the TOC lives. If null, returns a null value.
+     * @param hs The HelpSet context for this TOC. Null hs is ignored.
+     * @param locale The default locale to interpret the data in this TOC. Null locale 
+     * is treated as the default locale.
+     * @param factory A factory instance used to create the TOCItems.
+     * @param view The TOCView instance. May be null
+     * @return A TreeNode that represents the TOC. Returns null if parsing errors were
+     * encountered.
+     */
+    public static DefaultMutableTreeNode parse(URL url,
+					       HelpSet hs,
+					       Locale locale,
+					       TreeItemFactory factory,
+					       TOCView view) {
+	Reader src;
+	DefaultMutableTreeNode node = null;
+	try {
+	    URLConnection uc = url.openConnection();
+	    src = XmlReader.createReader(uc);
+	    factory.parsingStarted(url);
+	    TOCParser tocParser = new TOCParser(factory, view);
+	    node = (tocParser.parse(src, hs, locale));
+	    src.close();
+	} catch (Exception e) {
+	    factory.reportMessage("Exception caught while parsing "+url+
+				  e.toString(), false);
+	}
+	return factory.parsingEnded(node);
+    }
+
+    /**
+     * Set the default category open image ID.
+     *
+     * param String ID of catagory open image
+     */
+    public void setCategoryOpenImageID(String imageID) {
+	if (imageID == null) {
+	    return;
+	}
+	try {
+	    categoryOpenImageID = ID.create(imageID, getHelpSet());
+	} catch (BadIDException bex) {
+	}
+    }
+
+    /**
+     * Returns the default category open image ID.
+     *
+     * return ID the ID for the category open image, if the category open image
+     *        is null return the category closed image if it is defined,
+     *        otherwise return null
+     */
+    public ID getCategoryOpenImageID() {
+	if (categoryOpenImageID == null) {
+	    // if categoryOpenImageID is null return the categoryClosedImageID
+	    // it might be null but that is ok.
+	    return categoryClosedImageID;
+	}
+	return categoryOpenImageID;
+    }
+
+    /**
+     * Set the default category closed image ID.
+     *
+     * param String ID of catagory closed image
+     */
+    public void setCategoryClosedImageID(String imageID) {
+	if (imageID == null) {
+	    return;
+	}
+	try {
+	    categoryClosedImageID = ID.create(imageID, getHelpSet());
+	} catch (BadIDException bex) {
+	}
+    }
+
+    /**
+     * Returns the default category closed image ID.
+     *
+     * return ID the ID for the category closed image or null if not defined
+     */
+    public ID getCategoryClosedImageID() {
+	return categoryClosedImageID;
+    }
+
+    /**
+     * Set the topic image ID
+     *
+     * param String ID for the topic image
+     */
+    public void setTopicImageID(String imageID) {
+	if (imageID == null) {
+	    topicImageID = null;
+	    return;
+	}
+	try {
+	    topicImageID = ID.create(imageID, getHelpSet());
+	} catch (BadIDException bex) {
+	}
+    }
+
+    /**
+     * Returns the topic image ID.
+     *
+     * return String the ID for the topic image or null if not defined
+     */
+    public ID getTopicImageID() {
+	return topicImageID;
+    }
+
+    /**
+     * A default TreeItemFactory that can be used to parse TOC items as used
+     * by this navigator.
+     */
+    public static class DefaultTOCFactory implements TreeItemFactory {
+	private Vector messages = new Vector();
+	private URL source;
+	private boolean validParse = true;
+
+	/**
+	 * Starts parsing.
+	 */
+	public void parsingStarted(URL source) {
+	    if (source == null) {
+		throw new NullPointerException("source");
+	    }
+	    this.source = source;
+	}
+
+	/**
+	 * Processes a DOCTYPE.
+	 */
+	public void processDOCTYPE(String root, 
+				   String publicID,
+				   String systemID) {
+	    if (publicID == null ||
+		(publicID.compareTo(publicIDString) != 0 &&
+		 publicID.compareTo(publicIDString_V2) != 0)) {
+		reportMessage(HelpUtilities.getText("toc.wrongPublicID", publicID), false);
+	    }
+	}
+
+	/**
+	 * Finds a PI--ignore it.
+	 */
+	public void processPI(HelpSet hs, String target, String data) {
+	}
+
+	/**
+	 * Create an TOCItem with the given data.
+	 * @param tagName The TOC type to create. 
+	 * Valid types are "tocitem". Null or invalid types will throw an
+	 * IllegalArgumentException
+	 * @param atts Attributes of the Item. Valid attributes are "target",
+	 * "image", and "text". A null atts is valid and means no attributes
+	 * @param hs HelpSet this item was created under. 
+	 * @param locale Locale of this item. A null locale is valid. 
+	 * @returns A fully constructed TreeItem.
+	 * @throws IllegalArgumentExcetpion if tagname is null or invalid.
+	 */
+	public TreeItem createItem(String tagName,
+				   Hashtable atts,
+				   HelpSet hs,
+				   Locale locale) {
+	    if (tagName == null || !tagName.equals("tocitem")) {
+		throw new IllegalArgumentException("tagName");
+	    }
+	    TOCItem item = null;
+	    String id = null;
+	    String imageID = null;
+	    String text = null;
+            String mergeType = null;
+	    String expand = null;
+	    String presentation = null;
+	    String presentationName = null;
+
+	    if (atts != null) {
+		id = (String) atts.get("target");
+		imageID = (String) atts.get("image");
+		text = (String) atts.get("text");
+                mergeType = (String) atts.get("mergetype");
+		expand = (String) atts.get("expand");
+		presentation = (String) atts.get("presentationtype");
+		presentationName = (String) atts.get("presentationname");
+	    }
+
+	    Map.ID mapID = null;
+	    Map.ID imageMapID = null;
+	    try {
+		mapID = ID.create(id, hs);
+	    } catch (BadIDException bex1) {
+	    }
+	    try {
+		imageMapID = ID.create(imageID, hs);
+	    } catch (BadIDException bex2) {
+	    }
+	    item = new TOCItem(mapID, imageMapID, hs, locale);
+	    if (text != null) {
+		item.setName(text);
+	    }
+
+            if (mergeType != null){
+                item.setMergeType(mergeType);
+            }
+
+	    if (expand != null) {
+		if (expand.equals("true")) {
+		    item.setExpansionType(TreeItem.EXPAND);
+		} else if (expand.equals("false")) {
+		    item.setExpansionType(TreeItem.COLLAPSE);
+		}
+	    }
+		    
+            if (presentation != null){
+                item.setPresentation(presentation);
+            }
+
+            if (presentationName != null){
+                item.setPresentationName(presentationName);
+            }
+	    return item;
+	}
+	
+	/**
+	 * Creates a default TOCItem.
+	 */
+	public TreeItem createItem() {
+	    return new TOCItem();
+	}
+
+	/**
+	 * Reports an error message.
+	 */
+	public void reportMessage(String msg, boolean validParse) {
+	    messages.addElement(msg);
+	    this.validParse = this.validParse && validParse;
+	}
+
+	/**
+	 * Lists all the error messages.
+	 */
+	public Enumeration listMessages() {
+	    return messages.elements();
+	}
+
+	/**
+	 * Ends parsing.  Last chance to do something
+	 * to the node.
+	 * @param node The DefaultMutableTreeNode that has been built during the
+	 * the parsing. If <tt>node</tt> is null or there were parsing errors a null 
+	 * is returned.
+	 * @returns A valid DefaultMutableTreeNode if the parsing succeded or null
+	 * if it failed.
+	 */
+	public DefaultMutableTreeNode parsingEnded(DefaultMutableTreeNode node) {
+	    DefaultMutableTreeNode back = node;
+	    if (! validParse) {
+		// A parse with problems...
+		back = null;
+		System.err.println("Parsing failed for "+source);
+		for (Enumeration e = messages.elements();
+		     e.hasMoreElements();) {
+		    String msg = (String) e.nextElement();
+		    // need to think about this one...
+		    System.err.println(msg);
+		}
+	    }
+	    return back;
+	}
+    }
+
+
+    /**
+     * Inner class for parsing a TOC stream.
+     *
+     * WARNING!! This class is an interim solution until JavaHelp moves to a
+     * real XML parser.  This is not a public class.  Clients should only use
+     * the parse method in the enclosing class.
+     */
+    private static class TOCParser implements ParserListener {
+	private HelpSet currentParseHS;	// HelpSet we are parsing into
+	private Stack nodeStack;	// to track the parsing
+	private Stack itemStack;
+	private boolean startedtoc;
+	private Stack tagStack;
+	private Locale defaultLocale;
+	private Locale lastLocale;
+	private TreeItemFactory factory;
+	private TOCView tocView;
+
+
+	/**
+	 * Creates a TOC Parser using a factory instance to create the item nodes.
+	 *
+	 * @param factory The ItemTreeFactory instance to use when a node
+	 * has been recognized.
+	 */
+
+	TOCParser(TreeItemFactory factory, TOCView tocView) {
+	    this.factory = factory;
+	    this.tocView = tocView;
+	}
+
+	/**
+	 * Parses a reader into a DefaultMutableTreeNode.
+	 * Only one of these at a time.
+	 */
+	synchronized DefaultMutableTreeNode parse(Reader src,
+						  HelpSet context,
+						  Locale locale)
+	    throws IOException 
+	{
+	    nodeStack = new Stack();
+	    tagStack = new Stack();
+	    itemStack = new Stack();
+
+	    if (locale == null) {
+		defaultLocale = Locale.getDefault();
+	    } else {
+		defaultLocale = locale;
+	    }
+	    lastLocale = defaultLocale;
+	    
+	    DefaultMutableTreeNode node = new DefaultMutableTreeNode();
+	    nodeStack.push(node);
+	    
+	    currentParseHS = context;
+	    
+	    Parser parser = new Parser(src); // the XML parser instance
+	    parser.addParserListener(this);
+	    parser.parse();
+	    return node;
+	}
+
+	/**
+	 *  A Tag was parsed.
+	 */
+	public void tagFound(ParserEvent e) {
+	    Locale locale = null;
+	    Tag tag = e.getTag();
+	    debug("TagFound: "+tag.name);
+	    TagProperties attr = tag.atts;
+
+	    if (attr != null) {
+		String lang = attr.getProperty("xml:lang");
+		locale = HelpUtilities.localeFromLang(lang);
+	    }
+	    if (locale == null) {
+		locale = lastLocale;
+	    }
+
+	    if (tag.name.equals("tocitem")) {
+		if (!startedtoc) {
+		    factory.reportMessage(HelpUtilities.getText("toc.invalidTOCFormat"), false);
+		}
+		if (tag.isEnd && !tag.isEmpty) {
+		    nodeStack.pop();
+		    itemStack.pop();
+		    removeTag(tag);
+		    return;
+		}
+
+
+		TOCItem item;
+		try {
+		    Hashtable t = null;
+		    if (attr != null) {
+			t = attr.getHashtable();
+		    }
+		    item = (TOCItem) factory.createItem("tocitem",
+							t,
+							currentParseHS,
+							locale);
+		} catch (Exception ex) {
+		    if (warningOfFailures) {
+			String id = null;
+			String imageID = null;
+			if (attr != null) {
+			    id = attr.getProperty("target");
+			    imageID = attr.getProperty("image");
+			}
+			System.err.println("Failure in IndexItem Creation; ");
+			System.err.println("  id: "+id);
+			System.err.println("  hs: "+currentParseHS);
+		    }
+		    item = (TOCItem) factory.createItem();
+		}
+
+		if (!itemStack.empty()) {
+		    TOCItem parent = (TOCItem)itemStack.peek();
+		    if (item.getExpansionType() == TreeItem.DEFAULT_EXPANSION &&
+			parent != null && 
+			parent.getExpansionType() != TreeItem.DEFAULT_EXPANSION) {
+			item.setExpansionType(parent.getExpansionType());
+		    }
+		}
+		DefaultMutableTreeNode node = new DefaultMutableTreeNode(item);
+		DefaultMutableTreeNode parent =
+		    (DefaultMutableTreeNode) nodeStack.peek();
+		parent.add(node);
+		if (! tag.isEmpty) {
+		    itemStack.push(item);
+		    nodeStack.push(node);
+		    addTag(tag, locale);
+		}
+	    } else if (tag.name.equals("toc")) {
+		debug("attr: "+attr);
+		if (!tag.isEnd) {
+		    if (attr != null) {
+		        String version = attr.getProperty("version");
+			if (version != null && 
+			    (version.compareTo("1.0") != 0 &&
+			     version.compareTo("2.0") != 0)) {
+			    factory.reportMessage(HelpUtilities.getText("toc.unknownVersion",version), false);
+			}
+			if (tocView != null) {
+			    tocView.setCategoryOpenImageID(attr.getProperty("categoryopenimage"));
+			    tocView.setCategoryClosedImageID(attr.getProperty("categoryclosedimage"));
+			    tocView.setTopicImageID(attr.getProperty("topicimage"));
+			}
+		    }
+		    if (startedtoc) {
+			factory.reportMessage(HelpUtilities.getText("toc.invalidTOCFormat"), false);
+		    }
+		    startedtoc = true;
+		    addTag(tag, locale);
+		} else {
+		    if (startedtoc) {
+			startedtoc = false;
+		    }
+		    removeTag(tag);
+		}
+		return;
+	    }
+	}
+
+	/**
+	 *  A PI was parsed.  This method is not intended for general use.
+	 */
+	public void piFound(ParserEvent e) {
+	    // ignore
+	}
+
+	/**
+	 *  A DOCTYPE was parsed.  This method is not intended for general use.
+	 */
+	public void doctypeFound(ParserEvent e) {
+	    // ignore for now
+	}
+
+	/**
+	 * A continous block of text was parsed.
+	 */
+	public void textFound(ParserEvent e) {
+	    debug("TextFound: "+e.getText().trim());
+
+	    // Ignore text if there isn't a tag
+	    if (tagStack.empty()) {
+		return;
+	    }
+	    LangElement le = (LangElement) tagStack.peek();
+	    Tag tag = (Tag) le.getTag();
+	    if (tag.name.equals("tocitem")) {
+		TOCItem item = (TOCItem) itemStack.peek();
+		String oldName = item.getName();
+		if (oldName == null) {
+		    item.setName(e.getText().trim());
+		} else {
+		    item.setName(oldName.concat(e.getText()).trim());
+		}
+	    } 
+	}
+
+	// The remaing events from Parser are ignored
+	public void commentFound(ParserEvent e) {}
+
+	public void errorFound(ParserEvent e){
+	    factory.reportMessage(e.getText(), false);
+	}
+
+	/**
+	 * Tracks tags and their locale attributes.
+	 */
+	protected void addTag(Tag tag, Locale locale) {
+	    LangElement el = new LangElement(tag, locale);
+	    tagStack.push(el);
+	    // It's possible for lastLocale not be specified ergo null.
+	    // If it is then set lastLocale to null even if locale is null.
+	    // It is impossible for locale to be null
+	    if (lastLocale == null) {
+		lastLocale = locale;
+		return;
+	    }
+	    if (locale == null) {
+		lastLocale = locale;
+		return;
+	    }
+	    if (! lastLocale.equals(locale)) {
+		lastLocale = locale;
+	    }
+	}
+
+	/**
+	 * Removes a tag from the tagStack. The tagStack is
+	 * used to track tags and locales.
+	 */
+	protected void removeTag(Tag tag) {
+	    LangElement el;
+	    String name = tag.name;
+	    Locale newLocale = null;
+
+	    for (;;) {
+		if (tagStack.empty()) 
+		    break;
+		el = (LangElement) tagStack.pop();
+		if (el.getTag().name.equals(name)) {
+		    if (tagStack.empty()) {
+			newLocale = defaultLocale;
+		    } else {
+			el = (LangElement) tagStack.peek();
+			newLocale = el.getLocale();
+		    }
+		    break;
+		}
+	    }
+	    // It's possible for lastLocale not be specified ergo null.
+	    // If it is then set lastLocale to null even if locale is null.
+	    // It also possible for locale to be null so if lastLocale is set
+	    // then reset lastLocale to null;
+	    // Otherwise if lastLocale doesn't equal locale reset lastLocale to locale
+	    if (lastLocale == null) {
+		lastLocale = newLocale;
+		return;
+	    }
+	    if (newLocale == null) {
+		lastLocale = newLocale;
+		return;
+	    }
+	    if (! lastLocale.equals(newLocale)) {
+		lastLocale = newLocale;
+	    }
+	}
+
+    }
+
+    /**
+     * Debugging code
+     */
+    private static final boolean debug = false;
+    private static void debug(String msg) {
+	if (debug) {
+	    System.err.println("TOCView: "+msg);
+	}
+    }
+
+
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/TextHelpModel.java b/jhMaster/JavaHelp/src/new/javax/help/TextHelpModel.java
new file mode 100644
index 0000000000000000000000000000000000000000..30f3410b1be80c4aa9e119623048a3f56662d1de
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/TextHelpModel.java
@@ -0,0 +1,109 @@
+/*
+ * @(#)TextHelpModel.java	1.7 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help;
+
+import javax.help.event.*;
+
+/**
+ * The interface to a HelpModel that manipulates text.
+ *
+ * It provides additional text operations.
+ */
+
+public interface TextHelpModel extends HelpModel {
+    /**
+     * Gets the title of the document.
+     *
+     * @return The title of document visited.
+     */
+    public String getDocumentTitle();
+
+    /**
+     * Sets the title of the document.
+     * A property change event is generated.
+     *
+     * @param title The title currently shown.
+     */
+    public void setDocumentTitle(String title);
+
+
+    /**
+     * Removes all highlights on the current document.
+     */
+    public void removeAllHighlights();
+
+    /**
+     * Adds a highlight to a range of positions in a document.
+     *
+     * @param pos0 Start position.
+     * @param pos1 End position.
+     */
+    public void addHighlight(int pos0, int pos1);
+
+    /**
+     * Sets the highlights to be a range of positions in a document.
+     *
+     * @param h The array of highlight objects.
+     */
+    public void setHighlights(Highlight[] h);
+
+    /**
+     * Gets all highlights.
+     */
+    public Highlight[] getHighlights();
+
+    /**
+     * Adds a listener for a TextHelpModel.
+     */
+    public void addTextHelpModelListener(TextHelpModelListener l);
+
+    /**
+     * Removes a listener for a TextHelpModel.
+     */
+    public void removeTextHelpModelListener(TextHelpModelListener l);
+
+    /**
+     * This is very similar to javax.swing.text.Highlighter.Highlight
+     * except that it does not use the notion of HighlightPainter.
+     */
+    public interface Highlight {
+	/**
+	 * Gets the starting model offset of the highlight.
+	 *
+	 * @return The starting offset >= 0.
+	 */
+	public int getStartOffset();
+
+	/**
+	 * Gets the ending model offset of the highlight.
+	 *
+	 * @return The ending offset >= 0.
+	 */
+	public int getEndOffset();
+    }
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/TreeItem.java b/jhMaster/JavaHelp/src/new/javax/help/TreeItem.java
new file mode 100644
index 0000000000000000000000000000000000000000..c5c0eea4f9e86395f3c250b46a7da84a05b7bcbf
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/TreeItem.java
@@ -0,0 +1,257 @@
+/*
+ * @(#)TreeItem.java	1.28 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help;
+
+import javax.help.Map.ID;
+import java.util.Locale;
+import java.net.URL;
+import java.io.Serializable;
+import java.io.IOException;
+
+/**
+ * The base items known to TOC, Index and Favorites Navigators.
+ *
+ * @author Roger D. Brinkley
+ * @author Eduardo Pelegri-Llopart
+ * @author Richard Gregor
+ * @version   1.28     10/30/06
+ */
+
+public class TreeItem implements Serializable
+{
+
+    /**
+     * A state of expansion determined by the view
+     */
+    public static final int DEFAULT_EXPANSION = -1;
+
+    /**
+     * Show the children of the node collapsed in the view
+     */
+    public static final int COLLAPSE = 0;
+
+    /**
+     * Show the children of the node expanded in the view
+     */
+    public static final int EXPAND = 1;
+
+    private String name;
+    private ID id;
+    protected Locale locale;
+    private String mergeType;
+    private int expand = DEFAULT_EXPANSION;
+    private String presentation;
+    private String presentationName;
+    private HelpSet hs;
+
+     /**
+     * Create an TreeItem.
+     *
+     * @param id ID for the item. The ID can be null.
+     * @param hs A HelpSet scoping this item.
+     * @param locale The locale for this item
+     */
+    public TreeItem(ID id, HelpSet hs, Locale locale) {
+	this.id = id;
+	this.hs = hs;
+	this.locale = locale;
+    }
+
+   /**
+     * Creates a TreeItem.
+     *
+     * @param id ID for the item. Null is a valid ID.
+     * @param The lang for this item. A null is valid and indicates the default
+     * locale.
+     */
+    public TreeItem(ID id, Locale locale){
+	this (id, null, locale);
+    }
+    /**
+     * Creates a TreeItem.
+     *
+     * @param name The name for the item.
+     */
+    public TreeItem(String name){
+        this(null,null, null);
+        setName(name);
+    }
+    
+    /**
+     * Creates an empty TreeItem.
+     */
+    public TreeItem(){
+        this(null,null);        
+    }
+    /**
+     * Sets the name of the item.
+     */
+    public void setName(String name) {
+	this.name = name;
+    }
+
+    /**
+     * Returns the name of the item.
+     */
+    public String getName() {
+	return name;
+    }
+    
+    /**
+     * Set the ID for the item.
+     */
+    public void setID (ID id) {
+	this.id = id;
+    }
+
+    /**
+     * Returns the ID for the item.
+     */
+    public ID getID() {
+	return id;
+    }
+
+    /**
+     * Returns the URL for the item.
+     */
+    public URL getURL() {
+        try {
+            return id.getURL();
+        } catch (Exception e) {
+            return null;
+        }
+    }
+
+    /**
+     * Set the HelpSet for this TreeItem.
+     */
+    public void setHelpSet(HelpSet hs) {
+	this.hs = hs;
+    }
+
+    /**
+     * Returns the HelpSet scoping this IndexItem. Will return the ID HelpSet
+     * if one exists. Null otherwise
+     */
+    public HelpSet getHelpSet() {
+	return hs;
+    }
+    
+    /**
+     * Returns the locale for the item.
+     */
+    public Locale getLocale() {
+	return locale;
+    }
+    
+    /**
+     * Sets the merge type
+     */
+    public void setMergeType(String mergeType){
+        this.mergeType = mergeType;
+    }
+    
+    /**
+     * Returns the merge type for the item
+     */
+    public String getMergeType(){
+        return mergeType;
+    }
+
+    /**
+     * Sets the expansion type
+     * @throws IllegalArgumentException if not a valid type
+     */
+    public void setExpansionType(int type) {
+	if (type < DEFAULT_EXPANSION || type > EXPAND) {
+	    throw new IllegalArgumentException("Invalid expansion type");
+	}
+	expand = type;
+    }
+
+    /**
+     * Returns the exansion type
+     */
+    public int getExpansionType() {
+	return expand;
+    }
+
+    /**
+     * Sets the presentation
+     * @see Presentation
+     */
+    public void setPresentation(String presentation) {
+	this.presentation = presentation;
+    }
+
+    /**
+     * Returns the presentation
+     * @see Presentation
+     */
+    public String getPresentation() {
+	return presentation;
+    }
+
+    /**
+     * Sets the presentation name
+     * @see Presentation
+     */
+    public void setPresentationName(String presentationName) {
+	this.presentationName = presentationName;
+    }
+
+    /**
+     * Returns the presentation name
+     * @see Presentation
+     */
+    public String getPresentationName() {
+	return presentationName;
+    }
+
+    /**
+     * Returns a String used when displaying the object.
+     * Used by CellRenderers.
+     *
+     * @see TOCCellRenderer
+     */
+    public String toString() {
+	return (id+"("+name+")");
+    }
+
+    // for serialization
+     private void writeObject(java.io.ObjectOutputStream out) throws IOException {
+         //ignore so that FavoritesItem will work
+     }
+     
+     private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
+         //ignore so that FavoritesItem will work
+     }
+ 
+
+}
+
diff --git a/jhMaster/JavaHelp/src/new/javax/help/TreeItemFactory.java b/jhMaster/JavaHelp/src/new/javax/help/TreeItemFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..b2e2b6f65d2960fbe23687d3877bf2d203d31bd5
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/TreeItemFactory.java
@@ -0,0 +1,111 @@
+/*
+ * @(#)TreeItemFactory.java	1.9 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help;
+
+import java.util.Hashtable;
+import java.util.Locale;
+import java.util.Enumeration;
+import java.net.URL;
+import javax.swing.tree.DefaultMutableTreeNode;
+
+/**
+ * A factory for creating TreeItems.  This can be used to reuse the parsers.
+ *
+ * @author Eduardo Pelegri-Llopart
+ * @(#)TreeItemFactory.java 1.7 01/29/99
+ */
+
+public interface TreeItemFactory {
+    /**
+     * Starts parsing.
+     *
+     * @param source The URL of the document being parsed.
+     */
+    public void parsingStarted(URL source);
+
+
+    /**
+     * Processes a DOCTYPE.
+     *
+     * @param root The root tag of the document.
+     * @param publicID PublicID from the DOCTYPE.
+     * @param systemID SystemID from the DOCTYPE.
+     */
+    public void processDOCTYPE(String root, String publicID, String systemID);
+
+    /**
+     * A Processing Instruction.
+     *
+     * @param target The target of the PI.
+     * @param data A String for the data in the PI.
+     */
+    public void processPI(HelpSet hs,
+			  String target,
+			  String data);
+
+    /**
+     * Creates a TreeItem from the given data.
+     *
+     * @param tagName The name of the tag (for example, treeItem, or tocItem)
+     * @param attributes A hashtable with all the attributes.  Null is a valid value.
+     * @param hs A HelpSet that provides context.
+     * @param lang The locale.
+     * @return A TreeItem.
+     */
+    public TreeItem createItem(String tagName,
+			       Hashtable attributes,
+			       HelpSet hs,
+			       Locale locale);
+
+    /**
+     * Creates a default TreeItem.
+     *
+     * @return A TreeItem
+     */
+    public TreeItem createItem();
+
+    /**
+     * Reports a parsing error.
+     *
+     * @param msg The message to report.
+     * @param validParse Whether the result of the parse is still valid.
+     */
+    public void reportMessage(String msg, boolean validParse);
+
+    /**
+     * Lists all the error messages.
+     */
+    public Enumeration listMessages();
+
+    /**
+     * Ends parsing.  Last chance to do something
+     * to the node.  Return null to be sure the result is discarded.
+     */
+    public DefaultMutableTreeNode parsingEnded(DefaultMutableTreeNode node);
+}
+
diff --git a/jhMaster/JavaHelp/src/new/javax/help/TryMap.java b/jhMaster/JavaHelp/src/new/javax/help/TryMap.java
new file mode 100644
index 0000000000000000000000000000000000000000..c44feadf50d5646057fa36255fe937c5cb81000b
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/TryMap.java
@@ -0,0 +1,271 @@
+/*
+ * @(#)TryMap.java	1.19 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help;
+
+import java.net.URL;
+import java.net.MalformedURLException;
+import java.util.*;
+import java.io.*;
+import java.beans.*;
+import javax.help.event.*;
+import javax.help.Map.ID;
+
+/**
+ * A Map that can combine a number of other Maps in an 
+ * efficient manner.
+ *
+ * Currently this is a brute-force implementation.
+ *
+ * @author Eduardo Pelegri-Llopart
+ * @version	1.11	03/10/99
+ */
+public class TryMap implements Map, Serializable {
+    private Vector maps;	// All the maps
+
+    /**
+     * Creates an empty Map.
+     * This is useful for filtering and to add/remove to/from it.
+     */
+    public TryMap() {
+	maps = new Vector();
+    }
+
+    /**
+     * Adds a map to a "filter" Map.
+     * Adding a composed map to another is equivalent to
+     * adding the entire Map individually.
+     *
+     * @param map The new Map to add. If Map is null it is not added.
+     */
+    public void add(Map map) {
+	maps.addElement(map);
+    }
+
+    /**
+     * Removes a Map from this "filter" Map.
+     *
+     * @param map The Map to add.
+     * @return Whether the Map is already present. If the Map is
+     * null or was not previously added, returns "false".
+     */
+    public boolean remove(Map map) {
+	return maps.removeElement(map);
+    }
+
+    /**
+     * Enumerates all the Maps in this TryMap.
+     *
+     * @return An enumeration of the Maps added.
+     */
+    public Enumeration getMaps() {
+	return maps.elements();
+    }
+
+    /**
+     * Determines if the ID is valid (known to in the project file).
+     * 
+     * @param id The ID to check. A null ID is a valid parameter
+     * @param hs The HelpSet against which to resolve the string.
+     * @return True if id is valid, false if not valid.
+     */
+
+    public boolean isValidID(String id, HelpSet hs) {
+	debug("isValidID "+id);
+	for (Enumeration e = maps.elements();
+	     e.hasMoreElements();) {
+	    Map m = (Map) e.nextElement();
+	    if (m.isValidID(id, hs)) {
+		return true;
+	    }
+	}
+	return false;
+    }
+
+    /**
+     * Gets an enumeration of all the IDs in a Map.
+     *
+     * @param An enumeration of all the IDs in a Map.
+     */
+    public Enumeration getAllIDs() {
+	return new TryEnumeration(maps.elements(), null);
+    }
+
+    /**
+     * Gets the URL that corresponds to a given ID in the Map.
+     *
+     * @param id The ID for which to get the URL. If <tt>id</tt> is null it is
+     * treated as an unresolved ID and returns null.
+     * @return URL The matching URL.  Null if this Map cannot resolve the ID.
+     * @exception MalformedURLException if the URL specification found is malformed
+     */
+    public URL getURLFromID(ID id) throws MalformedURLException {
+	debug("getURLFromID("+id+")");
+	URL back = null;
+	for (Enumeration e = maps.elements();
+	     e.hasMoreElements(); ) {
+	    Map m = (Map) e.nextElement();
+	    back = m.getURLFromID(id);
+	    if (back != null) {
+		return back;
+	    }
+	}
+	return back;
+    }
+
+    /**
+     * Determines if the URL corresponds to an ID in the Map.
+     *
+     * @param url The URL to check on.
+     * @return True if this is an ID, false otherwise.
+     */
+    public boolean isID(URL url) {
+	for (Enumeration e = maps.elements();
+	     e.hasMoreElements(); ) {
+	    Map m = (Map) e.nextElement();
+	    if (m.isID(url)) {
+		return true;
+	    }
+	}
+	return false;
+    }
+
+
+    /**
+     * Determines the ID for this URL.
+     * 
+     * @param url The URL to get the ID for.
+     * @return The ID (Map.ID), or null if URL is not an ID
+     */
+    public ID getIDFromURL(URL url) {
+	debug("getIDFromURL("+url+")");
+	ID back = null;
+	for (Enumeration e = maps.elements();
+	     e.hasMoreElements(); ) {
+	    Map m = (Map) e.nextElement();
+	    back = m.getIDFromURL(url);
+	    if (back != null) {
+		return back;
+	    }
+	}
+	return null;
+    }
+
+    /**
+     * Determines the ID that is "closest" to this URL (with a given anchor).
+     *
+     * @param url A URL
+     * @return The closest ID in this map to the given URL
+     */
+    public ID getClosestID(URL url) {
+	ID back = null;
+	// See if there is an exact match
+	back = getIDFromURL(url);
+	if (back != null) {
+	    return back;
+	}
+
+	// for backwards compatability return a null if the URL is null
+	if (back == null && url == null) {
+	    return null;
+	}
+	 
+	// no exact match try removing the ref if there is one
+	String ref = url.getRef();
+	if (ref != null) {
+	    String urlString = url.toExternalForm();
+	    urlString = urlString.substring(0,urlString.lastIndexOf(ref)-1);
+	    try {
+		URL newURL = new URL(urlString);
+		for (Enumeration e = maps.elements();
+		     e.hasMoreElements(); ) {
+		    Map m = (Map) e.nextElement();
+		    back = m.getIDFromURL(newURL);
+		    if (back != null) {
+			return back;
+		    }
+		}
+	    } catch (MalformedURLException mue) {
+	    }
+	}
+	return null;
+    }
+
+    /**
+     * Gets the the IDs related to this URL.
+     *
+     * @param URL The URL to compare the Map IDs to.
+     * @return Enumeration of IDs (Strings)
+     */
+    public Enumeration getIDs(URL url) {
+	return new TryEnumeration(maps.elements(), url);
+    }
+
+    private static class TryEnumeration implements Enumeration {
+	private Enumeration e;	// the maps
+	private Enumeration k;	// the IDs within a map
+	private URL url;
+
+	public TryEnumeration(Enumeration e, URL url) {
+	    this.e = e;
+	    this.k = null;
+	    this.url = url;
+	}
+
+	public boolean hasMoreElements() {
+	    while (k == null ||
+		   !k.hasMoreElements()) {
+		if (! e.hasMoreElements()) {
+		    return false;
+		}
+		Map m = (Map) e.nextElement();
+		if (url == null) {
+		    k = m.getAllIDs();
+		} else {
+		    k = m.getIDs(url);
+		}
+	    }
+	    return k.hasMoreElements();
+	}
+
+	public Object nextElement() {
+	    return k.nextElement(); // this is an ID
+	}
+
+    }
+
+    /**
+     * For printf debugging.
+     */
+    private static final boolean debug = false;
+    private static void debug(String str) {
+        if (debug) {
+            System.out.println("TryMap: " + str);
+        }
+    }
+
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/UniteAppendMerge.java b/jhMaster/JavaHelp/src/new/javax/help/UniteAppendMerge.java
new file mode 100644
index 0000000000000000000000000000000000000000..40d57322dd40f9318944411f1965f551ac8b738d
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/UniteAppendMerge.java
@@ -0,0 +1,172 @@
+/*
+ * @(#)UniteAppendMerge.java	1.8 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help;
+
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.TreeNode;
+import java.util.Locale;
+/**
+ * Unite-append merge type
+ *
+ * @author Richard Gregor
+ * @version 	1.8	10/30/06
+ */
+
+public class UniteAppendMerge extends Merge{
+
+    /**
+     * Constructs UniteAppendMerge
+     *
+     * @param master The master NavigatorView
+     * @param slave The slave NavigatorView
+     */
+    public UniteAppendMerge(NavigatorView master, NavigatorView slave) {
+        super(master, slave);
+    }
+    
+    /**
+     * Processes unite-append merge 
+     *
+     * @param node The master node
+     * @return Merged master node
+     */
+    public TreeNode processMerge(TreeNode node) {
+        
+	DefaultMutableTreeNode masterNode = (DefaultMutableTreeNode) node;
+        
+        //if master and slave are the same object return the
+	// masterNode 
+        if (masterNode.equals(slaveTopNode)) {
+            return masterNode;
+        }
+        
+	// If there are not children in slaveTopNode return the
+	// masterNode
+        if (slaveTopNode.getChildCount() == 0) { 
+            return masterNode;
+        }
+        
+	mergeNodes(masterNode, slaveTopNode);
+        return masterNode;
+    }
+    
+    
+    /**
+     * Merge Nodes. Merge two nodes according to the UniteAppend merging rules 
+     *
+     * @param masterNode The master node to merge with 
+     * @param slaveNode The node to merge into the master
+     */
+    public static void mergeNodes(TreeNode master, TreeNode slave) {
+       DefaultMutableTreeNode masterNode = (DefaultMutableTreeNode)master;
+       DefaultMutableTreeNode slaveNode = (DefaultMutableTreeNode)slave;
+       debug("mergeNodes master=" + MergeHelpUtilities.getNodeName(masterNode) + 
+	     " slave=" + MergeHelpUtilities.getNodeName(slaveNode));       
+
+
+       int masterCnt = masterNode.getChildCount();
+
+       // loop thru the slaves
+       while (slaveNode.getChildCount() > 0) {
+	    DefaultMutableTreeNode slaveNodeChild = 
+		(DefaultMutableTreeNode)slaveNode.getFirstChild();
+	    
+	    //loop thru the master children
+	    for (int m=0; m < masterCnt; m++) {
+		DefaultMutableTreeNode masterAtM = 
+		    (DefaultMutableTreeNode)masterNode.getChildAt(m);
+		
+		// see if the names are the same
+		if (MergeHelpUtilities.compareNames(masterAtM, 
+						    slaveNodeChild) == 0) {
+		    // See if the IDs are the same
+		    if (MergeHelpUtilities.haveEqualID(masterAtM,
+							  slaveNodeChild)) {
+			// ID and name the same merge the slave node in
+			MergeHelpUtilities.mergeNodes("javax.help.UniteAppendMerge",
+						      masterAtM,
+						      slaveNodeChild);
+			// Need to remove the slaveNodeChild from the list
+			slaveNodeChild.removeFromParent();
+			slaveNodeChild = null;
+			break;
+		    } else {
+			// Names are the same but the ID are not
+			// Mark the nodes and add the slaveChild
+			MergeHelpUtilities.markNodes(masterAtM, 
+						     slaveNodeChild);
+			masterNode.add(slaveNodeChild);
+			MergeHelpUtilities.mergeNodeChildren("javax.help.UniteAppendMerge",
+							     slaveNodeChild);
+			slaveNodeChild = null;
+			break;
+		    }
+		}
+	    }
+	    if (slaveNodeChild != null) {
+		masterNode.add(slaveNodeChild);
+		MergeHelpUtilities.mergeNodeChildren("javax.help.UniteAppendMerge",
+						     slaveNodeChild);
+	    }
+       }
+       // There are no more children.
+       // Remove slaveNode from it's parent
+       slaveNode.removeFromParent();
+       slaveNode = null;
+    }
+
+    /**
+     * Merge Node Children. Merge the children of a node according to the
+     * UniteAppend merging.
+     *
+     * @param node The parent node from which the children are merged
+     */
+    public static void mergeNodeChildren(TreeNode node) {
+	DefaultMutableTreeNode masterNode = (DefaultMutableTreeNode)node;
+	debug("mergeNodes master=" + MergeHelpUtilities.getNodeName(masterNode));
+	
+	
+	// The rules are there are no rules. Nothing else needs to be done
+	// except for merging through the children
+	for (int i=0; i < masterNode.getChildCount(); i++) {
+	    DefaultMutableTreeNode child = 
+		(DefaultMutableTreeNode)masterNode.getChildAt(i);
+	    if (!child.isLeaf()) {
+		MergeHelpUtilities.mergeNodeChildren("javax.help.UniteAppendMerge", child);
+	    }
+	}
+    }
+
+    private static boolean debug = false;
+    private static void debug(String msg) {
+        if (debug) {
+            System.out.println("UniteAppendMerge :"+msg);
+	}
+    }
+     
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/UnsupportedOperationException.java b/jhMaster/JavaHelp/src/new/javax/help/UnsupportedOperationException.java
new file mode 100644
index 0000000000000000000000000000000000000000..d4e1decfdc9c01eb0f207d8c8d6b82ab872eae58
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/UnsupportedOperationException.java
@@ -0,0 +1,49 @@
+/*
+ * @(#)UnsupportedOperationException.java	1.4 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help;
+
+/**
+ * This is a platform-independent stand-in for the java.lang class
+ */
+public class UnsupportedOperationException extends RuntimeException {
+    
+    /**
+     * Constructs an UnsupportedOperationException with no detail message.
+     */
+    public UnsupportedOperationException() {
+    }
+    
+    /**
+     * Constructs an UnsupportedOperationException with the specified
+     * detail message. A null message is valid.
+     */
+    public UnsupportedOperationException(String message) {
+	super(message);
+    }
+    
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/WindowPresentation.java b/jhMaster/JavaHelp/src/new/javax/help/WindowPresentation.java
new file mode 100644
index 0000000000000000000000000000000000000000..68a9294271aaa7212468a486eb8eaebf053fdec0
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/WindowPresentation.java
@@ -0,0 +1,1109 @@
+/*
+ * @(#)WindowPresentation.java	1.22 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help;
+
+import javax.swing.JDialog;
+import javax.swing.JFrame;
+import javax.swing.SwingUtilities;
+import java.awt.Component;
+import java.awt.Dialog;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.Frame;
+import java.awt.GraphicsConfiguration;
+import java.awt.GraphicsDevice;
+import java.awt.GraphicsEnvironment;
+import java.awt.Image;
+import java.awt.MenuComponent;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.Window;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.awt.event.WindowListener;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.lang.reflect.Method;
+import java.net.URL;
+import java.util.Enumeration;
+import java.util.Locale;
+import javax.swing.ImageIcon;
+
+/**
+ * Window Presentation is an abstract class providing a generic interface for
+ * the development of Window Presentations. Each implementation of 
+ * Presentation will need to override the static method getPresentation
+ * according to it's own needs. 
+ *
+ * WindowPresentation implements several generic methods required in all 
+ * window presentations. Includes the ability to handle modal and non-modal
+ * activation of the help window.
+ *
+ * @author Roger D.Brinkley
+ * @version	1.22	10/30/06
+ * @since 2.0
+ *
+ * @see javax.help.HelpSet
+ * @see javax.help.JHelpNavigator
+ * @see javax.help.HelpVisitListener
+ */
+
+public abstract class WindowPresentation extends Presentation {
+
+    private HelpSet.Presentation hsPres=null;
+    private JFrame frame = null;
+    private JHelp jhelp = null;
+    private JDialog dialog = null;
+    private Window ownerWindow = null;
+    private boolean modallyActivated = false;
+    private Point location = null;
+    private String title = null;
+    private Image image = null;
+    private String currentView = null;
+    private boolean viewDisplayed = true;
+    private boolean toolbarDisplayed = true;
+    private boolean destroyOnExit = false;
+    private boolean titleFromDocument = false;
+    private WindowPropertyChangeListener propertyChangeListener = null;
+    private int screen = 0;
+
+    public WindowPresentation (HelpSet hs) {
+	setHelpSet(hs);
+    }
+
+    /**
+     * Set the Presentation attributes specific to WindowPresentations from a 
+     * named presentation in a HelpSet.
+     * 
+     * @params hsPres - the HelpSet.Presentation to retrieve the presentation 
+     *                  information from
+     * 
+     * @see HelpSet.Presentation
+     */
+    public void setHelpSetPresentation (HelpSet.Presentation hsPres) {
+	debug("setHelpSetPrsentation");
+	if (hsPres == null) {
+	    return;
+	}
+
+	// make sure the underlying presentation attributes are set
+	super.setHelpSetPresentation(hsPres);
+
+	// get the presentation location
+	Point location = hsPres.getLocation();
+	if (location != null) {
+	    setLocation(location);
+	}
+
+	// get the Title
+	String title = hsPres.getTitle();
+	if (title != null) {
+	    setTitle(title);
+	}
+
+	// get the imageID
+	javax.help.Map.ID imageID = hsPres.getImageID();
+	if (imageID != null) {
+	    ImageIcon icon = null;
+	    try {
+		javax.help.Map map = getHelpSet().getCombinedMap();
+		URL url = map.getURLFromID(imageID);
+		icon = new ImageIcon(url);
+		image = icon.getImage();
+	    } catch (Exception e) {
+	    }
+	}
+
+	if (hsPres.isToolbar()) {
+	    setToolbarDisplayed(true);
+	}
+
+	if (hsPres.isViewDisplayed()) {
+	    setViewDisplayed(true);
+	}
+	
+	this.hsPres = hsPres;
+    }
+
+    /**
+     * Return the HelpSet.Presentation if one was set
+     * @returns HelpSet.Presentation - the HelpSet.Presentation used in this
+     *		Presentation.
+     * 
+     * @see HelpSet.Presentation
+     */
+    public HelpSet.Presentation getHelpSetPresentation() {
+	return hsPres;
+    }
+
+    /**
+     * Get the activation window. 
+     *
+     * @returns Window - the activation window if activatated from a modal
+     *                   modal dialog, otherwise null.
+     */
+    public Window getActivationWindow() {
+	debug("getActivationWindow");
+	return ownerWindow;
+    }
+
+    /**
+     * Set the activation window. If the window is an instance of a
+     * Dialog and the is modal, modallyActivated help is set to true and 
+     * ownerDialog is set to the window. In all other instances 
+     * modallyActivated is set to false and ownerDialog is set to null.
+     * @param window the activating window
+     */
+    public void setActivationWindow(Window window) {
+	debug("setActivationWindow");
+	if (window != null && window instanceof Dialog) {
+	    Dialog tmpDialog = (Dialog) window;
+	    if (tmpDialog.isModal()) {
+		ownerWindow = window;
+		modallyActivated = true;
+	    } else {
+		ownerWindow = null;
+		modallyActivated = false;
+	    }
+	} else {
+	    ownerWindow = null;
+	    modallyActivated = false;
+	}
+    }
+		    
+    /**
+     * Set the activation window from given Component or MenuItem. It find Window component
+     * in the component tree from given Component or MenuItem end call 
+     * <pre>setActivationWindow</pre>.
+     * @parem comp the activation Component or MenuItem
+     * @since 2.0
+     *
+     * @see setActivationWindow
+     */
+    public void setActivationObject(Object comp) {
+	debug("setActivationObject");
+        while (comp instanceof MenuComponent) {
+            comp = ((MenuComponent)comp).getParent();
+        }
+        
+        Window owner = null;
+        if (comp instanceof Frame) {
+            owner = (Window)comp;
+        } else if (comp instanceof Component) {
+            owner = SwingUtilities.windowForComponent((Component)comp);
+        }
+        
+        setActivationWindow(owner);
+    }
+    
+    /**
+     * Determines the current navigator.
+     */
+    public String getCurrentView() {
+	debug("getCurrentView");
+	// always use the current view if the jhelp exists.
+	if (jhelp != null) {
+	    currentView = jhelp.getCurrentNavigator().getNavigatorName();
+	}
+	return currentView;
+    }
+
+
+    /**
+     * Set the currentView to the navigator with the same 
+     * name as the <tt>name</tt> parameter.
+     *
+     * @param name The name of the navigator to set as the 
+     * current view. If nav is null or not a valid Navigator 
+     * in this WindowPresentation then an 
+     * IllegalArgumentException is thrown.
+     * @throws IllegalArgumentException if nav is null or not a valid Navigator.
+     */
+    public void setCurrentView(String name) {
+	debug("setCurrentView");
+	// if the jhelp already exists then set the currentview
+	if (jhelp != null) {
+	    
+	    JHelpNavigator nav = getNavigatorByName(name);
+	    
+	    if (nav == null) {
+		throw new IllegalArgumentException("Invalid view name");
+	    }
+	    jhelp.setCurrentNavigator(nav);
+	} else {
+	    // jhelp didn't exist so make sure view is in HelpSet
+	    HelpSet hs = getHelpSet();
+	    NavigatorView view = hs.getNavigatorView(name);
+	    if (view == null) {
+		throw new IllegalArgumentException("Invalid view name");
+	    }
+	}
+	currentView = name;
+    }
+
+    /*
+     * Internal method to return a Navigator by name from a jhelp
+     */
+    private JHelpNavigator getNavigatorByName(String name) {
+	JHelpNavigator nav = null;
+	if (jhelp != null) {
+	    for (Enumeration e = jhelp.getHelpNavigators();
+		 e.hasMoreElements(); ) {
+		nav = (JHelpNavigator) e.nextElement();
+		if (nav.getNavigatorName().equals(name)) {
+		    break;
+		}
+		nav = null;
+	    }
+	}
+	return nav;
+    }
+
+
+    /**
+     * Determines if the presentation should be distroyed on exit
+     */
+    public boolean isDestroyedOnExit() {
+	debug("isDestoryedOnExit");
+	return destroyOnExit;
+    }
+
+    /**
+     * Destory the window on exit
+     */
+    public void setDestroyOnExit(boolean destroy) {
+	debug("setDestoryOnExit");
+	destroyOnExit = destroy;
+    }
+
+    /**
+     * Destroy this object. Implementation of WindowPresentation that
+     * maintian a list of objects should override this method and call 
+     * super.destroy to clear up the WindowPresentation internal fields.
+     */
+    public void destroy() {
+	frame = null;
+	jhelp = null;
+	dialog = null;
+	ownerWindow = null;
+	location = null;
+	title = null;
+	currentView = null;
+	propertyChangeListener = null;
+	screen = 0;
+    }
+
+    /**
+     * Changes the HelpSet for this presentation.
+     * @param hs The HelpSet to set for this presentation. 
+     * A null hs is valid parameter.
+     */
+    public void setHelpSet(HelpSet hs) {
+	debug("setHelpSet");
+
+	HelpSet helpset = super.getHelpSet();
+	// If we already have a model check if the HelpSet has changed.
+	// If so change the model
+	// This could be made smarter to cache the helpmodels per HelpSet
+	if (hs != null && helpset != hs) {
+	    super.setHelpSet(hs);
+	    if (jhelp != null) {
+		jhelp.setModel(super.getHelpModel());
+	    }
+	}
+    }
+
+    /**
+     * Displays the presentation to the user.
+     */
+    public void setDisplayed(boolean b) {
+	debug ("setDisplayed");
+	// if the jhelp is null and they don't want it displayed just return
+	if (jhelp == null && !b) {
+	    return;
+	}
+
+	// The call to createHelpWindow is necessary as the modality
+	// might have been changed and we need to change from a dialog
+	// to a frame. This is only done in createHelpWindow.
+	createHelpWindow();
+	if (modallyActivated) {
+	    if (b) {
+		dialog.show();
+	    } else {
+		dialog.hide();
+	    }
+	} else {
+	    frame.setVisible(b);
+
+	// We should be able to just 
+	// try {
+	// 	frame.setState(Frame.NORMAL)
+	// } catch (NoSuchMethodError ex) {
+	// }
+	// but IE4.0 barfs very badly at this
+	// So...
+
+	    try {
+		Class types[] = {Integer.TYPE};
+		Method m = Frame.class.getMethod("setState", types);
+
+		if (m != null) {
+		    Object args[] = {new Integer(0)}; // Frame.NORMAL
+		    m.invoke(frame, args);
+		}
+	    } catch (NoSuchMethodError ex) {
+		// as in JDK1.1
+	    } catch (NoSuchMethodException ex) {
+		// as in JDK1.1
+	    } catch (java.lang.reflect.InvocationTargetException ex) {
+		//
+	    } catch (java.lang.IllegalAccessException ex) {
+		//
+	    }
+	}
+    }
+
+    /**
+     * Determines if the presentation is displayed.
+     */
+    public boolean isDisplayed() {
+	debug ("isDisplayed");
+	if (jhelp == null) {
+	    return false;
+	}
+	if (modallyActivated) {
+	    if (dialog != null) {
+		return dialog.isShowing();
+	    } else {
+		return false;
+	    }
+	} else {
+	    if (frame != null) {
+		if (! frame.isShowing()) {
+		    return false;
+		}
+		else {
+		    // We should be able to just 
+		    // try {
+		    // 	return (frame.getState() == Frame.NORMAL)
+		    // } catch (NoSuchMethodError ex) {
+		    // }
+		    // but IE4.0 barfs very badly at this
+		    // So...
+
+		    try {
+			Method m = Frame.class.getMethod("getState", 
+							 (java.lang.Class[]) null);
+
+			if (m != null) {
+			    int value =((Integer)(m.invoke(frame, 
+							   (java.lang.Object[])null))).intValue();
+			    if (value == 0)
+				return true;
+			    else 
+				return false;
+
+			}
+		    } catch (NoSuchMethodError ex) {
+			// as in JDK1.1
+		    } catch (NoSuchMethodException ex) {
+			// as in JDK1.1
+		    } catch (java.lang.reflect.InvocationTargetException ex) {
+			//
+		    } catch (java.lang.IllegalAccessException ex) {
+			//
+		    }
+		    // On 1.1 I can't tell if it's raised or not.
+		    // It's on the screen so true.
+		    return true;
+		}
+	    } else {
+		return false;
+	    }
+	}
+    }
+
+    /**
+     * Sets the font for this this WindowPresentation.
+     * @param f The font.
+     */
+    public void setFont (Font f) {
+	debug("setFont");
+	super.setFont(f);
+	if (jhelp != null && f != null) {
+	    jhelp.setFont(f);
+	}
+    }
+
+    /**
+     * Gets the font for this WindowPresentation
+     */
+    public Font getFont() {
+	debug("getFont");
+	Font font = super.getFont();
+	if (font == null) {
+	    if (jhelp == null) {
+		createHelpWindow();
+	    }
+	    return jhelp.getFont();
+	}
+	return font;
+    }
+
+    /**
+     * Sets the locale of this Presentation. The locale is propagated to
+     * the presentation.
+     * @param l The locale to become this component's locale. A null locale
+     * is the same as the defaultLocale.
+     * @see #getLocale
+     */
+    public void setLocale(Locale l) { 
+	debug("setLocale");
+	super.setLocale(l);
+	if (jhelp != null) {
+	    jhelp.setLocale(l);
+	}
+    }
+
+
+    /**
+     * internal method to test for Xinerama mode
+     */
+    private boolean isXinerama () {
+	GraphicsEnvironment ge = 
+	    GraphicsEnvironment.getLocalGraphicsEnvironment();
+	GraphicsDevice[] gds = ge.getScreenDevices();
+	if (gds.length == 1) {
+	    return false;
+	} else {
+	    for (int i=0; i<gds.length; i++) {
+		GraphicsConfiguration loopgc =
+		    gds[i].getDefaultConfiguration();
+		Rectangle bounds = loopgc.getBounds();
+		if (bounds.x != 0 || bounds.y !=0) {
+		    return true;
+		}
+	    }
+	}
+	return false;
+    }
+
+   /**
+     * Requests the location of the presentation.
+     * 
+     * @returns Point the location of the presentation.
+     */
+    public Point getLocation() {
+	debug("getLocation");
+	if (location != null && jhelp == null) {
+	    return location;
+	}
+	if (jhelp == null) {
+	    createHelpWindow();
+	}
+	if (modallyActivated) {
+	    Point dlocation = dialog.getLocation();
+	    if (isXinerama()) {
+		GraphicsConfiguration gc = dialog.getGraphicsConfiguration();
+		Rectangle gcBounds = gc.getBounds();
+		return new Point(dlocation.x - gcBounds.x,
+				 dlocation.y - gcBounds.y);
+	    } 
+	    return dlocation;
+	} else {
+	    Point flocation = frame.getLocation();
+	    if (isXinerama()) {
+		GraphicsConfiguration gc = frame.getGraphicsConfiguration();
+		Rectangle gcBounds = gc.getBounds();
+		return new Point(flocation.x - gcBounds.x,
+				 flocation.y - gcBounds.y);
+	    } 
+	    return flocation;
+	}
+    }
+
+    /**
+     * Requests the presentation be located at a given position.
+     */
+    public void setLocation(Point p) {
+	debug("setLocation");
+	location = p;
+
+
+	if (jhelp != null) {
+	    if (modallyActivated) {
+		if (dialog != null) {
+		    GraphicsConfiguration gc = 
+			dialog.getGraphicsConfiguration();
+		    Rectangle gcBounds = gc.getBounds();
+		    Point loc = new Point (gcBounds.x + p.x, 
+					   gcBounds.y + p.y);
+		    dialog.setLocation(loc);
+		}
+	    } else {
+		if (frame != null) {
+		    GraphicsConfiguration gc = 
+			frame.getGraphicsConfiguration();
+		    Rectangle gcBounds = gc.getBounds();
+		    Point loc = new Point (gcBounds.x + p.x, 
+					   gcBounds.y + p.y);
+		    frame.setLocation(loc);
+		}
+	    }
+	}
+    }
+
+    /** 
+     * Requests the screen of the presentation
+     * @returns int the screen of the presentation
+     */
+    public int getScreen() {
+	debug("getScreen");
+	// If there is no jhelp componet then it hasn't been "realized"
+	// yet so just return the screen
+	if (jhelp == null) {
+	    return screen;
+	}
+
+	// Help is showing so get the screen from the presentation
+	GraphicsConfiguration gc = null;
+	if (modallyActivated) {
+	    if (dialog != null) {
+		gc = dialog.getGraphicsConfiguration();
+	    }
+	} else {
+	    if (frame != null) {
+		gc = frame.getGraphicsConfiguration();
+	    }
+	}
+	if (gc != null) {
+	    GraphicsDevice device = gc.getDevice();
+	    GraphicsEnvironment ge = 
+		GraphicsEnvironment.getLocalGraphicsEnvironment();
+	    GraphicsDevice[] gs = ge.getScreenDevices();
+	    for (int i=0; i < gs.length; i++) {
+		if (gs[i] == device) {
+		    // got our match
+		    screen = i;
+		    return screen;
+		}
+	    }
+	}
+	return screen;
+    }
+
+    /**
+     * Sets the screen of the presentation
+     * @param screen the screen number
+     * @throws IllegalArgumentException if the screen is invalid
+     */
+    public void setScreen(int screen) {
+	debug ("setScreen");
+
+	if (screen == this.screen) {
+	    // There is nothing to do as it is either already the screen
+	    // or the 
+	    return;
+	}
+
+	if (screen < 0) {
+	    throw new IllegalArgumentException("Invalid screen");
+	}
+
+	GraphicsEnvironment ge = 
+	    GraphicsEnvironment.getLocalGraphicsEnvironment();
+	GraphicsDevice[]gs = ge.getScreenDevices();
+
+	// make sure there is a screen device
+	if (gs.length <= screen) {
+	    throw new IllegalArgumentException ("Invalid Screen");
+	}
+
+	this.screen = screen;
+
+	if (jhelp != null) {
+
+	    boolean xinerama = isXinerama();
+	    
+	    GraphicsDevice gd = gs[screen];
+	    GraphicsConfiguration gc = gd.getDefaultConfiguration();
+	    Rectangle gcBounds = gc.getBounds();
+	    if (modallyActivated) {
+		if (dialog != null) {
+		    if (xinerama) {
+			Point p = getLocation();
+			Point loc = new Point (gcBounds.x + p.x, 
+					       gcBounds.y + p.y);
+			dialog.setLocation(loc);
+		    } else {
+			location = getLocation();
+			dialog.hide();
+			dialog = null;
+			createHelpWindow();
+		    }
+		}
+	    } else {
+		if (frame != null) {
+		    if (xinerama) {
+			Point p = getLocation();
+			Point loc = new Point (gcBounds.x + p.x, 
+					       gcBounds.y + p.y);
+			frame.setLocation(loc);
+		    } else {
+			location = getLocation();
+			frame.setVisible(false);
+			frame = null;
+			createHelpWindow();
+		    }
+		}
+	    }
+	}
+    }
+
+    /**
+     * Requests the size of the presentation.
+     * @returns Point the location of the presentation.
+     */
+    public Dimension getSize() {
+	debug("getSize");
+	// if the jhelp is created then just use the current sizes 
+	if (jhelp != null) {
+	    if (modallyActivated) {
+		if (dialog != null) {
+		    return dialog.getSize();
+		}
+	    } else {
+		if (frame != null) {
+		    return frame.getSize();
+		}
+	    }
+	}
+	return super.getSize();
+    }
+
+    /**
+     * Requests the presentation be set to a given size. Updates the
+     * the presentation on the fly. This is an override of 
+     * Presentation.SetSize.
+     */
+    public void setSize(Dimension d) {
+	debug("setSize");
+	super.setSize(d);
+	if (jhelp != null) {
+	    if (modallyActivated) {
+		dialog.setSize(d);
+		dialog.validate();
+	    } else {
+		frame.setSize(d);
+		frame.validate();
+	    }
+	}
+    }
+
+    public String getTitle() {
+	debug("getTitle");
+
+	// if the title comes from the document use that first if 
+	// jhelp exists
+	if (titleFromDocument && jhelp != null) {
+	    String docTitle = jhelp.getContentViewer().getDocumentTitle();
+	    if (docTitle != null) {
+		return docTitle;
+	    }
+	}
+	
+	// otherwise use the title that has been set...
+	if (title != null) {
+	    return title;
+	} else {
+	    // Unless there wasn't a title set and then use the HelpSet
+	    // title
+	    HelpSet hs = getHelpSet();
+	    if (hs != null) {
+		title = hs.getTitle();
+	    }
+	}
+	return title;
+    }
+
+    public void setTitle(String title) {
+	debug("setTitle");
+	this.title = title;
+	if (jhelp != null) {
+	    if (modallyActivated) {
+		dialog.setTitle(title);
+		dialog.validate();
+	    } else {
+		frame.setTitle(title);
+		frame.validate();
+	    }
+	}
+
+    }
+
+    /**
+     * Is the title set from the Document. This is generally useful
+     * in SecondaryWindows.
+     * @return boolean True if title is set from the Document, false otherwise.
+     */
+    public boolean isTitleSetFromDocument() {
+	debug("isTitleSetFromDocument");
+	return titleFromDocument;
+    }
+
+    /**
+     * Set the title from the Document. 
+     * @param b if true will set the title form the document, otherwise will
+     *	set the title from the HelpSet.
+     */
+    public void setTitleFromDocument(boolean b) {
+	debug("setTitleFromDocument");
+	if (titleFromDocument != b) {
+	    titleFromDocument = b;
+	    if (titleFromDocument) {
+		propertyChangeListener = new WindowPropertyChangeListener();
+		if (jhelp != null) {
+		    jhelp.getContentViewer().
+			addPropertyChangeListener("page",
+						  propertyChangeListener);
+		}
+	    } else {
+		if (jhelp != null) {
+		    jhelp.getContentViewer().
+			removePropertyChangeListener("page",
+						     propertyChangeListener);
+		}
+	    }
+	}
+    }
+
+    /**
+     * Determines if the current view is visible.
+     */
+    public boolean isViewDisplayed() {
+	debug ("isViewDisplayed");
+	if (jhelp != null) {
+	    return jhelp.isNavigatorDisplayed();
+	}
+	return viewDisplayed;
+    }
+
+    /**
+     * Hides/Shows view.
+     */
+    public void setViewDisplayed(boolean displayed) {
+	debug ("setViewDisplayed");
+	if (jhelp != null) {
+	    jhelp.setNavigatorDisplayed(displayed);
+	}
+	viewDisplayed = displayed;
+    }
+
+    /**
+     * Determines if the toolbar is visible.
+     */
+    public boolean isToolbarDisplayed() {
+	debug ("isToolbarDisplayed");
+	if (jhelp != null) {
+	    return jhelp.isToolbarDisplayed();
+	}
+	return toolbarDisplayed;
+    }
+
+    /**
+     * Hides/Shows Toolbar
+     */
+    public void setToolbarDisplayed(boolean displayed) {
+	debug ("setToolbarDisplayed=" + displayed);
+	if (jhelp != null) {
+	    jhelp.setToolbarDisplayed(displayed);
+	}
+	toolbarDisplayed = displayed;
+    }
+
+    private synchronized void createJHelp() {
+	debug ("createJHelp");
+	if (jhelp == null) {
+	    jhelp = new JHelp(getHelpModel(), null, getHelpSetPresentation());
+	    Font font = super.getFont();
+	    if (font != null) {
+		jhelp.setFont(font);
+	    }
+	    Locale locale = getLocale();
+	    if (locale != null) {
+		jhelp.setLocale(locale);
+	    }
+	    jhelp.setToolbarDisplayed(toolbarDisplayed);
+	    jhelp.setNavigatorDisplayed(viewDisplayed);
+	    if (currentView != null) {
+		JHelpNavigator nav = getNavigatorByName(currentView);
+		if (nav != null) {
+		    jhelp.setCurrentNavigator(nav);
+		}
+	    }
+	    if (titleFromDocument) {
+		jhelp.getContentViewer().
+		    addPropertyChangeListener("page", propertyChangeListener);
+	    }
+	}
+    }
+
+    WindowListener dl;
+    boolean modalDeactivated = true;
+
+    public synchronized void createHelpWindow() {
+	debug ("createHelpWindow");
+	// pos is used for determining the screen adjust location of a 
+	// dialog or frame that already exist. This should only be used
+	// when a switch is required. If it is null this is a creation.
+	Point pos = null;
+	Dimension size = getSize();
+	JDialog tmpDialog = null;
+
+	createJHelp();
+
+	
+	// The graphics variables below are only used during the initial
+	// creation. If there is a modality change then the actual position
+	// of the Window would be used instead.
+	GraphicsEnvironment ge = 
+	    GraphicsEnvironment.getLocalGraphicsEnvironment();
+	GraphicsDevice[] gds = ge.getScreenDevices();
+	GraphicsDevice gd = gds[screen];
+	GraphicsConfiguration gc = gd.getDefaultConfiguration();
+	Rectangle gcBounds = gc.getBounds();
+
+	if (modallyActivated) {
+	    // replace dialog.getOwner() with the following code
+	    Window owner=null;
+	    try {
+		Method m = Window.class.getMethod("getOwner", 
+						  (java.lang.Class[]) null);
+		
+		if (m != null && dialog != null) {
+		    owner = (Window) m.invoke(dialog, 
+					      (java.lang.Class[]) null);
+		}
+	    } catch (NoSuchMethodError ex) {
+		// as in JDK1.1
+	    } catch (NoSuchMethodException ex) {
+		// as in JDK1.1
+	    } catch (java.lang.reflect.InvocationTargetException ex) {
+		//
+	    } catch (java.lang.IllegalAccessException ex) {
+		//
+	    }
+	    
+	    if (dialog == null || owner != ownerWindow || modalDeactivated) {
+		if (frame != null) {
+		    // pos is already screen adjusted
+		    pos = frame.getLocation();
+		    size = frame.getSize();
+		    frame = null;
+		}
+		if (dialog != null) {
+		    // pos is already screen adjusted
+		    pos = dialog.getLocation();
+		    size = dialog.getSize();
+		    tmpDialog = dialog;
+		}
+		dialog = new JDialog((Dialog)ownerWindow, getTitle(), 
+				     false, gc);
+
+		// Modal dialogs are really tricky. When the modal dialog
+		// is dismissed the JDialog will be dismissed as well.
+		// When that happens we need to make sure the ownerWindow
+		// is set to null so that a new dialog will be created so
+		// that events aren't blocked in the HelpViewer.
+		dl = new WindowAdapter() {
+		    public void windowClosing(WindowEvent e) {
+			debug ("modal window closing");
+			if (destroyOnExit) {
+			    destroy();
+			    return;
+			}
+			// JDK1.2.1 bug not closing owned windows
+			if (dialog.isShowing()) {
+			    dialog.hide();
+			}
+			if (ownerWindow != null)
+			    ownerWindow.removeWindowListener(dl);
+			ownerWindow = null;
+			modalDeactivated = true;
+		    }
+
+		    public void windowClosed(WindowEvent e) {
+			debug ("modal window closing");
+			if (destroyOnExit) {
+			    destroy();
+			    return;
+			}
+		    }
+		};
+		debug ("adding windowlistener");
+
+		ownerWindow.addWindowListener(dl);
+		modalDeactivated = false;
+		if (size != null) {
+		    dialog.setSize(size);
+		} else {
+		    dialog.setSize(getSize());
+		}
+
+		// if the pos variable is not null then either a frame
+		// or a dialog already exists and you should use that position
+		// instead. If it is null then base the point on the location
+		// and screen or just the screen
+		if (pos != null) {
+		    dialog.setLocation(pos);
+		} else {
+		    // set based on location and screen or just screen
+		    Point loc = null;
+		    if (location != null) {
+			if (isXinerama()) {
+			    loc = new Point (gcBounds.x + location.x, 
+					     gcBounds.y + location.y);
+			} else {
+			    loc = location;
+			}
+			dialog.setLocation(loc);
+		    }
+		}
+		dialog.setTitle(getTitle());
+		dialog.getContentPane().add(jhelp);
+		if (tmpDialog != null) {
+		    tmpDialog.hide();
+		    tmpDialog = null;
+		}
+	    }
+	} else {
+	    if (frame == null) { 
+		frame = new JFrame(getTitle(), gc);
+
+		WindowListener l = new WindowAdapter() {
+		    public void windowClosing(WindowEvent e) {
+			if (destroyOnExit) {
+			    destroy();
+			    return;
+			}
+			frame.setVisible(false);
+		    }
+		    public void windowClosed(WindowEvent e) {
+			frame.setVisible(false);
+			if (destroyOnExit) {
+			    destroy();
+			    return;
+			}
+		    }
+		};
+		frame.addWindowListener(l);
+		if (image != null) {
+		    frame.setIconImage(image);
+		}
+	    }
+	    if (dialog != null) {
+		// pos is already screen adjusted
+		pos = dialog.getLocation();
+		size = dialog.getSize();
+		dialog.hide();
+		dialog = null;
+		ownerWindow = null;
+	    }
+	    if (size != null) {
+		frame.setSize(size);
+	    } else {
+		frame.setSize(getSize());
+	    }
+
+
+	    // if the pos variable is not null then either a frame
+	    // or a dialog already exists and you should use that position
+	    // instead. If it is null then base the point on the location
+	    // and screen or just the screen
+	    if (pos != null) {
+		frame.setLocation(pos);
+	    } else {
+		// set based on location and screen or just screen
+		Point loc = null;
+		if (location != null) {
+		    if (isXinerama()) {
+			loc = new Point (gcBounds.x + location.x, 
+					 gcBounds.y + location.y);
+		    } else {
+			loc = location;
+		    }
+		    frame.setLocation(loc);
+		}
+	    }
+	    frame.getContentPane().add(jhelp);
+            frame.setTitle(getTitle());
+	}
+
+    }                 
+
+    /**
+     * Get the current window that help is displayed in
+     *
+     * @returns Window the current Window
+     */
+    public Window getHelpWindow() {
+	if (modallyActivated) {
+	    return dialog;
+	}
+	return frame;
+    }
+
+    private class WindowPropertyChangeListener implements PropertyChangeListener {
+	public void propertyChange(PropertyChangeEvent event) {
+	    String changeName = event.getPropertyName();
+	    if (changeName.equals("page")) {
+		String title = getTitle();
+		if (modallyActivated) {
+		    dialog.setTitle(title); 
+		} else {
+		    frame.setTitle(title);
+		}
+	    }
+	}
+    }
+
+    /**
+     * Debugging code...
+     */
+
+    private static final boolean debug = false;
+    private static void debug(Object msg) {
+	if (debug) {
+	    System.err.println("WindowPresentation: "+msg);
+	}
+    }
+ 
+}
+
+
diff --git a/jhMaster/JavaHelp/src/new/javax/help/event/EventListenerList.java b/jhMaster/JavaHelp/src/new/javax/help/event/EventListenerList.java
new file mode 100644
index 0000000000000000000000000000000000000000..3df508b70732706d0dc481c988e1d1c57c1511aa
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/event/EventListenerList.java
@@ -0,0 +1,273 @@
+/*
+ * @(#)EventListenerList.java	1.9 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help.event;
+
+import java.io.*;
+import java.util.*;
+
+/**
+ * This class is a copy of the javax.swing.event.EventListenerList class.
+ *
+ * It is duplicated here because we do not want to introduce a dependency
+ * on Swing to HelpSet and DefaultHelpModel, which are otherwise Swing-free.
+ */
+
+/**
+ * A class that holds a list of EventListeners.  A single instance
+ * can be used to hold all listeners (of all types) for the instance
+ * using the list.  It is the responsiblity of the class using the
+ * EventListenerList to provide a type-safe API (preferably conforming
+ * to the JavaBeans specification) and methods that dispatch event notification
+ * methods to appropriate Event Listeners on the list.
+ * 
+ * The main benefits this class provides are that it is relatively
+ * cheap if there are no listeners, provides serialization for 
+ * eventlistener lists in a single place, and provides a degree of MT safety
+ * (when used correctly).
+ *
+ * Usage example:
+ *    If one is defining a class that sends out FooEvents, and wants
+ * to allow users of the class to register FooListeners and receive 
+ * notification when FooEvents occur.  The following should be added
+ * to the class definition:
+   <pre>
+   EventListenerList listenrList = new EventListnerList();
+   FooEvent fooEvent = null;
+
+   public void addFooListener(FooListener l) {
+       listenerList.add(FooListener.class, l);
+   }
+
+   public void removeFooListener(FooListener l) {
+       listenerList.remove(FooListener.class, l);
+   }
+
+ 
+    // Notify all listeners that have registered interest for
+    // notification on this event type.  The event instance 
+    // is lazily created using the parameters passed into 
+    // the fire method.
+
+    protected void firefooXXX() {
+	// Guaranteed to return a non-null array
+	Object[] listeners = listenerList.getListenerList();
+	// Process the listeners last to first, notifying
+	// those that are interested in this event
+	for (int i = listeners.length-2; i>=0; i-=2) {
+	    if (listeners[i]==FooListener.class) {
+		// Lazily create the event:
+		if (fooEvent == null)
+		    fooEvent = new FooEvent(this);
+		((FooListener)listeners[i+1]).fooXXX(fooEvent);
+	    }	       
+	}
+    }	
+   </pre>
+ * foo should be changed to the appropriate name, and Method to the
+ * appropriate method name (one firing method should exist for each
+ * notification method in the FooListener interface).
+ * <p>
+ * Warning: Serialized objects of this class are not be compatible with
+ * future Swing releases.  The current serialization support is appropriate 
+ * for short term storage or RMI between Swing1.0 applications.  It will
+ * not be possible to load serialized Swing1.0 objects with future releases
+ * of Swing.  The JDK1.2 release of Swing will be the compatibility
+ * baseline for the serialized form of Swing objects.
+ *
+ * @version 1.19 03/18/98
+ * @author Georges Saab
+ * @author Hans Muller
+ * @author James Gosling
+ */
+public class EventListenerList implements Serializable {
+    /* A null array to be shared by all empty listener lists*/
+    private final static Object[] NULL_ARRAY = new Object[0];
+    /* The list of ListenerType - Listener pairs */
+    protected transient Object[] listenerList = NULL_ARRAY;
+
+    /**
+     * This passes back the event listener list as an array
+     * of ListenerType - listener pairs.  Note that for 
+     * performance reasons, this implementation passes back 
+     * the actual data structure in which the listener data
+     * is stored internally!  
+     * This method is guaranteed to pass back a non-null
+     * array, so that no null-checking is required in 
+     * fire methods.  A zero-length array of Object should
+     * be returned if there are currently no listeners.
+     * 
+     * WARNING!!! Absolutely NO modification of
+     * the data contained in this array should be made -- if
+     * any such manipulation is necessary, it should be done
+     * on a copy of the array returned rather than the array 
+     * itself.
+     */
+    public Object[] getListenerList() {
+	return listenerList;
+    }
+
+    /**
+     * Returns the total number of listeners for this listenerList.
+     */
+    public int getListenerCount() {
+	return listenerList.length/2;
+    }
+
+    /**
+     * Returns the total number of listeners of the supplied type 
+     * for this listenerList.
+     */
+    public int getListenerCount(Class t) {
+	int count = 0;
+	Object[] lList = listenerList;
+	for (int i = 0; i < lList.length; i+=2) {
+	    if (t == (Class)lList[i])
+		count++;
+	}
+	return count;
+    }
+    /**
+     * Adds the listener as a listener of the specified type.
+     * @param t The type of the listener to be added.
+     * @param l The listener to be added.
+     * @throws IllegalArgumentException if <tt>l</tt> or <tt>t</tt> is 
+     * null or <tt>t</tt> is not an instance of <tt>l</tt>.
+     */
+    public synchronized void add(Class t, EventListener l) {
+	if (l ==null || t == null) {
+	    throw new IllegalArgumentException("Listener " + l +
+					 " is null");
+	}
+	if (!t.isInstance(l)) {
+	    throw new IllegalArgumentException("Listener " + l +
+					 " is not of type " + t);
+	}
+	if (listenerList == NULL_ARRAY) {
+	    // if this is the first listener added, 
+	    // initialize the lists
+	    listenerList = new Object[] { t, l };
+	} else {
+	    // Otherwise copy the array and add the new listener
+	    int i = listenerList.length;
+	    Object[] tmp = new Object[i+2];
+	    System.arraycopy(listenerList, 0, tmp, 0, i);
+
+	    tmp[i] = t;
+	    tmp[i+1] = l;
+
+	    listenerList = tmp;
+	}
+    }
+
+    /**
+     * Removes the listener as a listener of the specified type. If the
+     * listener for a given class does not exist in the list, it is ignored.
+     * @param t The type of the listener to be removed.
+     * @param l The listener to be removed.
+     * @throws IllegalArgumentException if <tt>l</tt> or <tt>t</tt> is 
+     * null or <tt>t</tt> is not an instance of <tt>l</tt>.
+     */
+    public synchronized void remove(Class t, EventListener l) {
+	if (l == null || t == null) {
+	    throw new IllegalArgumentException("Listener " + l +
+					 " is null");
+	}
+
+	if (!t.isInstance(l)) {
+	    throw new IllegalArgumentException("Listener " + l +
+					 " is not of type " + t);
+	}
+	// Is l on the list?
+	int index = -1;
+	for (int i = listenerList.length-2; i>=0; i-=2) {
+	    if ((listenerList[i]==t) && (listenerList[i+1] == l)) {
+		index = i;
+		break;
+	    }
+	}
+	
+	// If so,  remove it
+	if (index != -1) {
+	    Object[] tmp = new Object[listenerList.length-2];
+	    // Copy the list up to index
+	    System.arraycopy(listenerList, 0, tmp, 0, index);
+	    // Copy from two past the index, up to
+	    // the end of tmp (which is two elements
+	    // shorter than the old list)
+	    if (index < tmp.length)
+		System.arraycopy(listenerList, index+2, tmp, index, 
+				 tmp.length - index);
+	    // set the listener array to the new array or null
+	    listenerList = (tmp.length == 0) ? NULL_ARRAY : tmp;
+	    }
+    }
+
+    // Serialization support.  
+    private void writeObject(ObjectOutputStream s) throws IOException {
+	Object[] lList = listenerList;
+	s.defaultWriteObject();
+	
+	// Save the non-null event listeners:
+	for (int i = 0; i < lList.length; i+=2) {
+	    Class t = (Class)lList[i];
+	    EventListener l = (EventListener)lList[i+1];
+	    if ((l!=null) && (l instanceof Serializable)) {
+		s.writeObject(t.getName());
+		s.writeObject(l);
+	    }
+	}
+	
+	s.writeObject(null);
+    }
+
+    private void readObject(ObjectInputStream s) 
+	throws IOException, ClassNotFoundException {
+        listenerList = NULL_ARRAY;
+	s.defaultReadObject();
+	Object listenerTypeOrNull;
+	
+	while (null != (listenerTypeOrNull = s.readObject())) {
+	    EventListener l = (EventListener)s.readObject();
+	    add(Class.forName((String)listenerTypeOrNull), l);
+	}	    
+    }
+
+    /**
+     * Returns a string representation of the EventListenerList.
+     */
+    public String toString() {
+	Object[] lList = listenerList;
+	String s = "EventListenerList: ";
+	s += lList.length/2 + " listeners: ";
+	for (int i = 0 ; i <= lList.length-2 ; i+=2) {
+	    s += " type " + ((Class)lList[i]).getName();
+	    s += " listener " + lList[i+1];
+	}
+	return s;
+    }
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/event/HelpHistoryModelEvent.java b/jhMaster/JavaHelp/src/new/javax/help/event/HelpHistoryModelEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..3f4d5d74818f9e48d52ff192dcd92cf15a9f45a7
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/event/HelpHistoryModelEvent.java
@@ -0,0 +1,76 @@
+/*
+ * @(#)HelpHistoryModelEvent.java	1.4 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help.event;
+
+/**
+ * Notifies interested parties that a change in a
+ * Help History Model source has occurred.
+ *
+ * @author  Richard Gregor
+ * @version   1.4     10/30/06
+ */
+
+public class HelpHistoryModelEvent extends java.util.EventObject{
+
+    private boolean next;
+    private boolean previous;    
+    
+    /**
+     * Represents a history change 
+     *
+     * @param source The source for this event.
+     * @param previous If true a previous action is allowed.
+     * @param next If true a next action is allowed.
+     * @throws IllegalArgumentException if source is null.
+     */
+    public HelpHistoryModelEvent(Object source, boolean previous, 
+				 boolean next) {
+        super(source);
+        this.next = next;
+        this.previous = previous;        
+    }
+    
+    /**
+     * Returns if action "previous" is allowed.
+     * 
+     * @return True if action is allowed, false otherwise. 
+     */
+    public boolean isPrevious(){
+        return previous;
+    }
+    
+    /**
+     * Returns if action "next" is allowed
+     *
+     * @return True if action is allowed, false otherwise.
+     */
+    public boolean isNext() {
+        return next;
+    }
+    
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/event/HelpHistoryModelListener.java b/jhMaster/JavaHelp/src/new/javax/help/event/HelpHistoryModelListener.java
new file mode 100644
index 0000000000000000000000000000000000000000..34bd1cd2898b34044758dadedfd446f6f4fafcf1
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/event/HelpHistoryModelListener.java
@@ -0,0 +1,44 @@
+/*
+ * @(#)HelpHistoryModelListener.java	1.2 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+
+package javax.help.event;
+
+/**
+ * @author  Richard Gregor
+ * @version   1.2     10/30/06
+ */
+
+public interface HelpHistoryModelListener extends java.util.EventListener{
+    /**
+     * Tells the listener that the history has changed.
+     *
+     * @param e The HelpHistoryModelEvent
+     */
+    public void historyChanged(HelpHistoryModelEvent e);
+
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/event/HelpModelEvent.java b/jhMaster/JavaHelp/src/new/javax/help/event/HelpModelEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..90a45ecdf2869d5609dbd10df61051c46aff3c00
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/event/HelpModelEvent.java
@@ -0,0 +1,155 @@
+/*
+ * @(#)HelpModelEvent.java	1.21 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help.event;
+
+import java.net.URL;
+import java.util.Vector;
+import java.util.Enumeration;
+import javax.help.HelpSet;
+import javax.help.Map.ID;
+import javax.help.JHelpNavigator;
+
+
+/**
+ * Notifies interested parties that a change in a
+ * Help Model source has occurred.
+ *
+ * @author Roger D. Brinkley
+ * @author Eduardo Pelegri-Llopart
+ * @author Richard Gregor
+ * @version	1.16	03/10/99
+ */
+
+public class HelpModelEvent extends java.util.EventObject {
+    private ID id;
+    private URL url;
+    private String historyName;
+    private JHelpNavigator navigator;
+
+    /**
+     * Represents a change in the JavaHelp in the current ID or URL.
+     * @see javax.help.JavaHelp
+     * 
+     * @param source The source for this event.
+     * @param id The ID that has changed. Should be null if URL is specified.
+     * @param url The URL that has changed. Should be null if ID is specified.
+     * @throws IllegalArgumentException if source is null.
+     * @throws IllegalArgumentException of both ID and URL are null.
+     */
+    public HelpModelEvent(Object source, ID id, URL url) {
+	this(source,id,url,(String)null, (JHelpNavigator)null);
+    }
+    
+    /**
+     * Represents a change in the JavaHelp in the current ID or URL.
+     * @see javax.help.JavaHelp
+     * 
+     * @param source The source for this event.
+     * @param id The ID that has changed. Should be null if URL is specified.
+     * @param url The URL that has changed. Should be null if ID is specified.
+     * @param historyName The name of selected entry
+     * @param navigator The JHelpNavigator
+     * @throws IllegalArgumentException if source is null.
+     * @throws IllegalArgumentException of both ID and URL are null.
+     */
+    public HelpModelEvent(Object source, ID id, URL url, String historyName, JHelpNavigator navigator){
+        super(source);
+	if ((id == null) && (url == null)) {
+	  throw new IllegalArgumentException("ID or URL must not be null");
+	}
+        this.id = id;
+        this.url = url;
+        this.historyName = historyName;
+        this.navigator = navigator;
+    }
+        
+
+    /**
+     * Creates a HelpModelEvent for highlighting.
+     *
+     * @param source The source for this event.
+     * @param pos0 Start position.
+     * @param pos1 End position.
+     * @throws IllegalArgumentException if source is null.
+     */
+    public HelpModelEvent(Object source, int pos0, int pos1) {
+	super (source);
+	this.pos0 = pos0;
+	this.pos1 = pos1;
+    }
+    /**
+     * Returns the current ID in the HelpModel.
+     * @return The current ID.
+     */
+    public ID getID() {
+	return id;
+    }
+
+    /**
+     * Returns the current URL in the HelpModel.
+     * @return The current URL.
+     */
+    public URL getURL() {
+	return url;
+    }
+    
+    /**
+     * Returns the name of this entry
+     *
+     * @return The entry name
+     */
+    public String getHistoryName() {
+        return historyName;
+    }
+
+    /**
+     * Returns the navigator of this entry
+     *
+     * @return The navigator name
+     */
+    public JHelpNavigator getNavigator() {
+        return navigator;
+    }
+    
+    private int pos0, pos1;
+
+    // HERE - Review this highlighting; it is a different type of beast than the rest - epll
+    /**
+     * @return The start position of this (highlighting) event.
+     */
+    public int getPos0() {
+	return pos0;
+    }
+
+    /**
+     * @return The end position of this (highlighting) event.
+     */
+    public int getPos1() {
+	return pos1;
+    }
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/event/HelpModelListener.java b/jhMaster/JavaHelp/src/new/javax/help/event/HelpModelListener.java
new file mode 100644
index 0000000000000000000000000000000000000000..8b31e5109fccf399ba552ee67fa7cb1840aeb499
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/event/HelpModelListener.java
@@ -0,0 +1,48 @@
+/*
+ * @(#)HelpModelListener.java	1.15 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help.event;
+
+/**
+ * Defines the interface for an object that listens to 
+ * changes in a HelpModel.
+ *
+ * @author Roger D. Brinkley
+ * @author Eduardo Pelegri-Llopart
+ * @version	1.13	01/29/99
+ */
+
+public interface HelpModelListener extends java.util.EventListener {
+    /**
+     * Tells the listener that the current ID in the HelpModel has
+     * changed.
+     * All highlights from the previous location change at this point.
+     *
+     * @param e The event
+     */
+    public void idChanged(HelpModelEvent e);
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/event/HelpSetEvent.java b/jhMaster/JavaHelp/src/new/javax/help/event/HelpSetEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..9ccb78e37219633ed8e9859eb9d4cceac6ee1988
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/event/HelpSetEvent.java
@@ -0,0 +1,99 @@
+/*
+ * @(#)HelpSetEvent.java	1.13 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help.event;
+
+import javax.help.HelpSet;
+
+/**
+ * Conveys information when a HelpSet is added/removed.
+ *
+ * @author Eduardo Pelegri-Llopart
+ * @version	1.10	03/10/99
+ */
+
+public class HelpSetEvent extends java.util.EventObject {
+
+    /**
+     * Creates a HelpSetEvent.
+     *
+     * @param source Source of this Event.
+     * @param helpset The HelpSet being added/removed.
+     * @param action HELPSET_ADDED or HELPSET_REMOVED.
+     * @throws IllegalArgumentException if source is null or if action is not
+     * a valid action.
+     */
+     public HelpSetEvent(Object source, HelpSet helpset, int action) {
+	 super(source);
+         this.helpset = helpset;
+	 if (helpset == null) {
+	     throw new NullPointerException("helpset");
+	 }
+         this.action = action;
+	 if (action < 0 || action > 1) {
+	     throw new IllegalArgumentException("invalid action");
+	 }
+     }
+
+    /**
+     * A HelpSet was added
+     */
+     public static final int HELPSET_ADDED = 0;
+
+    /**
+     * A HelpSet was removed
+     */
+     public static final int HELPSET_REMOVED = 1;
+
+    /**
+     * @return The HelpSet.
+     */
+     public HelpSet getHelpSet() {
+	return helpset;
+     }
+
+    /**
+     * @return The action
+     */
+     public int getAction() {
+        return action;
+     }
+
+    /**
+     * Returns textual about the instance. 
+     */
+    public String toString() {
+	if (action==HELPSET_ADDED) {
+	    return "HelpSetEvent("+source+", "+helpset+"; added";
+	} else {
+	    return "HelpSetEvent("+source+", "+helpset+"; removed";
+	}
+    }
+
+     private HelpSet helpset;
+     private int action;
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/event/HelpSetListener.java b/jhMaster/JavaHelp/src/new/javax/help/event/HelpSetListener.java
new file mode 100644
index 0000000000000000000000000000000000000000..0961522da54a7a0b2232796112399f8a156236f0
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/event/HelpSetListener.java
@@ -0,0 +1,53 @@
+/*
+ * @(#)HelpSetListener.java	1.10 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help.event;
+
+/**
+ * Defines the interface of an object that listens to 
+ * changes in the HelpSet.
+ *
+ * @author Eduardo Pelegri-Llopart
+ * @version	1.8	01/29/99
+ */
+
+public interface HelpSetListener extends java.util.EventListener {
+
+    /**
+     * Invoked when a new HelpSet is added.
+     *
+     * @param e The event
+     */
+    public void helpSetAdded(HelpSetEvent e);
+
+    /**
+     * Invoked when a new HelpSet is removed.
+     *
+     * @param e The event
+     */
+    public void helpSetRemoved(HelpSetEvent e);
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/event/TextHelpModelEvent.java b/jhMaster/JavaHelp/src/new/javax/help/event/TextHelpModelEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..75f9c484ac913dc2a4d5a63dca9091c05f6518b1
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/event/TextHelpModelEvent.java
@@ -0,0 +1,56 @@
+/*
+ * @(#)TextHelpModelEvent.java	1.6 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help.event;
+
+import java.net.URL;
+import java.util.Vector;
+import java.util.Enumeration;
+import javax.help.HelpSet;
+import javax.help.Map.ID;
+
+/**
+ * Notifies interested parties when a change in a
+ * TextHelpModel occurs.  The listener should query the source
+ * for details.
+ *
+ * @author Eduardo Pelegri-Llopart
+ * @author Roger D. Brinkley
+ * @version	1.6	10/30/06
+ */
+
+public class TextHelpModelEvent extends java.util.EventObject {
+    /**
+     * Creates a TextHelpModelEvent.
+     *
+     * @param source The source for this event.  Implements TextHelpModel
+     * @throws IllegalArgumentException if source is null.
+     */
+    public TextHelpModelEvent(Object source) {
+	super (source);
+    }
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/event/TextHelpModelListener.java b/jhMaster/JavaHelp/src/new/javax/help/event/TextHelpModelListener.java
new file mode 100644
index 0000000000000000000000000000000000000000..ddf69752707ca6f44cc5df42c4b6f3340269d958
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/event/TextHelpModelListener.java
@@ -0,0 +1,47 @@
+/*
+ * @(#)TextHelpModelListener.java	1.5 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help.event;
+
+/**
+ * Defines the interface for an object that listens to 
+ * changes in a TextHelpModel.
+ *
+ * @author Eduardo Pelegri-Llopart
+ * @author Roger D. Brinkley
+ * @version	1.5	10/30/06
+ */
+
+public interface TextHelpModelListener extends java.util.EventListener {
+    /**
+     * Invoked when the set of highlights changess.
+     * Note that this event is <em>not</em> generated when an idChanged() event
+     * is generated, since all the highlights are reset at that point.
+     */
+    public void highlightsChanged(TextHelpModelEvent e);
+
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/event/package.html b/jhMaster/JavaHelp/src/new/javax/help/event/package.html
new file mode 100644
index 0000000000000000000000000000000000000000..d5563edfe48af13462aa6246cadd5aae836620a2
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/event/package.html
@@ -0,0 +1,65 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<!--
+
+  @(#)package.html	1.1 98/10/15
+
+  Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+  DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+  This code is free software; you can redistribute it and/or modify it
+  under the terms of the GNU General Public License version 2 only, as
+  published by the Free Software Foundation.  Sun designates this
+  particular file as subject to the "Classpath" exception as provided
+  by Sun in the LICENSE file that accompanied this code.
+
+  This code is distributed in the hope that it will be useful, but WITHOUT
+  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+  version 2 for more details (a copy is included in the LICENSE file that
+  accompanied this code).
+
+  You should have received a copy of the GNU General Public License version
+  2 along with this work; if not, write to the Free Software Foundation,
+  Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+  Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+  CA 95054 USA or visit www.sun.com if you need additional information or
+  have any questions.
+
+-->
+
+</head>
+<body bgcolor="white">
+
+Supports event changes in JavaHelp classes.
+<code>HelpModelEvent</code> and
+<code>HelpModelListener</code> support changes to the
+locations within HelpSets being presented,
+<code>TextHelpModelEvent</code> and
+<code>TextHelpModelListener</code> support textual changes
+and <code>HelpSetEvent</code>, and
+<code>HelpSetListener</code> support changes to the HelpSet
+itself.
+
+<p>
+<code>EventListenerList</code> is used as a convenience
+class to maintain lists of listeners and it is functionally
+equivalent to the equivalent Swing class--it is included to
+avoid adding unwanted dependencies on Swing.
+
+<!--
+<H2>Package Specification</H2>
+Link to updated API specification to be added here.
+-->
+
+<H2>Related Documentation</H2>
+
+<P>
+For overviews, tutorials, examples, guides, tool support,
+and other documentation,
+please see the <em>JavaHelp System User's Guide</em>.
+
+  </body>
+</html>
diff --git a/jhMaster/JavaHelp/src/new/javax/help/package.html b/jhMaster/JavaHelp/src/new/javax/help/package.html
new file mode 100644
index 0000000000000000000000000000000000000000..6b5215492bc08c96f63150a8667da3abf3772a0e
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/package.html
@@ -0,0 +1,155 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<!--
+
+  @(#)package.html	1.4 98/10/19
+
+  Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+  DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+  This code is free software; you can redistribute it and/or modify it
+  under the terms of the GNU General Public License version 2 only, as
+  published by the Free Software Foundation.  Sun designates this
+  particular file as subject to the "Classpath" exception as provided
+  by Sun in the LICENSE file that accompanied this code.
+
+  This code is distributed in the hope that it will be useful, but WITHOUT
+  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+  version 2 for more details (a copy is included in the LICENSE file that
+  accompanied this code).
+
+  You should have received a copy of the GNU General Public License version
+  2 along with this work; if not, write to the Free Software Foundation,
+  Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+  Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+  CA 95054 USA or visit www.sun.com if you need additional information or
+  have any questions.
+
+-->
+
+</head>
+<body bgcolor="white">
+
+Supports presentation of online documentation with both
+content and contextual views of this information.
+This is the main package for the JavaHelp standard extension.
+The main focus of JavaHelp is online help,
+but it can be used for any online content.
+
+<p>
+JavaHelp supports the notion of a HelpSet that encompases
+all documentation information.
+There is a simple way to read a HelpSet,
+create a presentation for it, and interact with it
+and there is also a collection of Swing components that
+can be used directly for additional control.
+JavaHelp presents content using Swing's EditorKits,
+which provide for extensibility of content.
+JavaHelp also provides for extensibility of context via
+the notion of a NavigatorView;
+several views are standard.
+One of the standard views provides full-text search,
+which relies on a simple search package to communicate with
+search engines.
+
+
+<h3>Basic Classes</h3>
+
+<code>HelpSet</code> is the main class, providing
+access to a HelpSet file.
+A visual presentation of a HelpSet can be obtained through
+a <code>HelpBroker</code> which is an abstraction
+that permits interaction regardless of the presentation
+details;
+the default presentation is <code>DefaultHelpBroker</code>.
+An application can provide online help using only these two classes.
+
+<p>
+Helpsets can be merged dynamically or statically, and
+can be associated with Beans.
+
+<h3>Swing components</h3>
+
+JavaHelp provides a collection of Swing components that are used to
+implement the DefaultHelpBroker and can also be used directly.  The
+components follow the standard MVC from Swing.
+<code>HelpModel</code> models changes to the location within a
+HelpSet--components that want to respond to these changes should
+listen to events originating within the model (this is how
+synchronized views work).  <code>TextHelpModel</code> provides
+additional information when the content is textual.
+<code>DefaultHelpModel</code> is the default model that implements both
+models.
+
+<p>
+<code>JHelpContentViewer</code>
+is the Swing component for HTML content,
+while context corresponds to several subclasses of
+<code>JHelpNavigator</code>.
+<code>JHelp</code> is a common grouping of these
+classes into synchronized views of content.
+
+
+<h3>Extensibility</h3>
+
+Context extensibility is described through a
+<code>NavigatorView</code> which provides access to context
+information, plus a way of presenting this information.
+<code>TOCView</code>, <code>IndexView</code>, and
+<code>SearchView</code> are standard views for table of contents,
+index, and full-text search.
+
+<p>
+The standard views yield standard <code>JHelpTOCNavigator</code>,
+<code>JHelpIndexNavigator</code>, and
+<code>JHelpSearchNavigator</code> Swing components.  The standard
+views also provide access to the content--this access is
+provides through subclasses
+of <code>TreeItem</code>.
+
+<p>
+New views can be added,
+for instance a new TOC presentation can be obtained by
+subclassing TOCView and changing the JHelpNavigator
+returned by it.
+
+<h3>Context Sensitive Help</h3>
+
+JavaHelp supports a <code>Map</code> between identifiers and URLs.
+<code>FlatMap</code> and <code>TryMap</code> are two
+implementations.
+
+The main class used to associate specific content with graphic
+objects is <code>CSH</code>, while <code>DialogSupport</code>
+provides support in Dialogs (this may migrate to Swing at some
+point).
+
+<h3>Search</h3>
+JavaHelp supports a standard full-text search view and navigator.
+The view interacts with a search engine through the types in the
+<code>javax.javahelp.search</code> package.  The reference
+implementation provides a search engine that implements these interfaces,
+but others can also be used. The specific search engine is part
+of the information given to the search view.  This separation
+provides the full-text search functionality but does not
+imposing specific formats.
+
+
+<!--
+<H2>Package Specification</H2>
+<p>
+Link to updated API specification to be added here.
+-->
+
+<H2>Related Documentation</H2>
+
+<P>
+For overviews, tutorials, examples, guides, tool support,
+and other documentation,
+please see the <em>JavaHelp System User's Guide</em>.
+
+  </body>
+</html>
diff --git a/jhMaster/JavaHelp/src/new/javax/help/plaf/HelpContentViewerUI.java b/jhMaster/JavaHelp/src/new/javax/help/plaf/HelpContentViewerUI.java
new file mode 100644
index 0000000000000000000000000000000000000000..a992ad978979e84eafd49395d83ec573838b99cc
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/plaf/HelpContentViewerUI.java
@@ -0,0 +1,42 @@
+/*
+ * @(#)HelpContentViewerUI.java	1.14 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help.plaf;
+
+import javax.swing.plaf.ComponentUI;
+import javax.swing.text.EditorKit;
+import javax.help.event.HelpModelEvent;
+/**
+ * UI factory interface for JHelpContentViewer.
+ *
+ * @author Eduardo Pelegri-Llopart
+ * @author Roger Brinkley
+ * @version   1.14     10/30/06
+ */
+
+public abstract class HelpContentViewerUI extends ComponentUI {
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/plaf/HelpNavigatorUI.java b/jhMaster/JavaHelp/src/new/javax/help/plaf/HelpNavigatorUI.java
new file mode 100644
index 0000000000000000000000000000000000000000..0ec0b369a34d1c820ddf9303e630a5461f456684
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/plaf/HelpNavigatorUI.java
@@ -0,0 +1,113 @@
+/*
+ * @(#)HelpNavigatorUI.java	1.26 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help.plaf;
+
+import javax.swing.plaf.ComponentUI;
+import javax.swing.plaf.*;
+import javax.swing.Icon;
+import javax.swing.ImageIcon;
+import javax.help.HelpModel;
+import javax.help.event.HelpModelListener;
+import javax.help.event.HelpModelEvent;
+import javax.help.NavigatorView;
+import javax.help.Map;
+import java.net.URL;
+import javax.swing.Action;
+import javax.swing.AbstractAction;
+
+/**
+ * UI factory interface for JHelpNavigator.
+ *
+ * @author Roger D. Brinkley
+ * @author Eduardo Pelegri-Llopart
+ * @author Stepan Marek
+ * @version   %I     10/30/06
+ */
+
+public abstract class HelpNavigatorUI extends ComponentUI {
+
+    private Icon icon;
+
+    /**
+     * Sets the icon for this HelpNavigator.
+     *
+     * @param icon the Icon
+     */
+    public void setIcon(Icon icon) {
+	this.icon = icon;
+    }
+
+    /**
+     * @return the Icon for this HelpNavigator
+     */
+    public Icon getIcon() {
+	return icon;
+    }
+
+    /**
+     * Merges a Navigator View.
+     */
+    public void merge(NavigatorView view){
+        throw new UnsupportedOperationException("merge is not supported");
+    }
+
+    /**
+     * Removes a Navigator View.
+     */
+    public void remove(NavigatorView view){
+        throw new UnsupportedOperationException("remove is not supported");
+    }
+    
+    /**
+     * Returns icon associated with the view.
+     *
+     * @param view the view
+     * @return the ImageIcon for the view
+     */
+    public ImageIcon getImageIcon(NavigatorView view) {
+        ImageIcon icon = null;
+        Map.ID id = view.getImageID();
+        if (id != null) {
+            try {
+                Map map = view.getHelpSet().getCombinedMap();
+                URL url = map.getURLFromID(id);
+                icon = new ImageIcon(url);
+		} catch (Exception e) {
+		}
+        }
+        return icon;
+    }
+    
+    /**
+     * Returns an AddAction object. Has sense only for favorites navigator
+     */
+    public Action getAddAction(){
+        throw new UnsupportedOperationException("getAddAction is not supported");
+        //return (Action)null;
+    }
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/plaf/HelpUI.java b/jhMaster/JavaHelp/src/new/javax/help/plaf/HelpUI.java
new file mode 100644
index 0000000000000000000000000000000000000000..f2873252e892cd3aa785d3b31acc144544ad91cb
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/plaf/HelpUI.java
@@ -0,0 +1,73 @@
+/*
+ * @(#)HelpUI.java	1.21 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help.plaf;
+
+import javax.swing.plaf.ComponentUI;
+import javax.swing.plaf.*;
+import javax.help.JHelpNavigator;
+import java.util.Enumeration;
+
+/**
+ * UI factory interface for JHelp.
+ *
+ * @author Roger D. Brinkley
+ * @author Eduardo Pelegri-Llopart
+ * @version   1.21     10/30/06
+ */
+
+public abstract class HelpUI extends ComponentUI {
+
+    /**
+     * Adds a Navigator.
+     *
+     * @param nav the Navigator to add
+     */
+   public abstract void addNavigator(JHelpNavigator nav);
+
+    /**
+     * Remove a Navigator.
+     *
+     * @param nav The Navigator to remove.
+     */
+   public abstract void removeNavigator(JHelpNavigator nav);
+
+    /**
+     * Sets the current Navigator.
+     *
+     * @param nav The current Navigator to show.
+     */
+    public abstract void setCurrentNavigator(JHelpNavigator nav);
+
+    /**
+     * Gets the current Navigator.
+     *
+     * @param nav The current Navigator to show.
+     */
+    public abstract JHelpNavigator getCurrentNavigator();
+
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicContentViewerUI.java b/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicContentViewerUI.java
new file mode 100644
index 0000000000000000000000000000000000000000..70d040d4054326be786363510dd3ced3d9e20e3e
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicContentViewerUI.java
@@ -0,0 +1,607 @@
+/*
+ * @(#)BasicContentViewerUI.java	1.57 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+/*
+ * @(#) BasicContentViewerUI.java 1.57 - last change made 10/30/06
+ */
+
+package javax.help.plaf.basic;
+
+import javax.help.*;
+import javax.help.plaf.HelpContentViewerUI;
+import javax.help.event.*;
+import java.util.Vector;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.Hashtable;
+import javax.swing.*;
+import javax.swing.text.*;
+import javax.swing.text.html.HTMLEditorKit;
+import javax.swing.text.html.StyleSheet;
+import javax.swing.plaf.ComponentUI;
+import javax.swing.plaf.TextUI;
+import javax.swing.border.*;
+import javax.swing.event.*;
+import javax.swing.text.html.*;
+import javax.swing.text.html.parser.*;
+import javax.swing.text.Element;
+import java.awt.*;
+import java.awt.event.*;
+import java.net.URL;
+import java.net.MalformedURLException;
+import java.net.URLConnection;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.io.*;
+import javax.help.Map.ID;
+
+/**
+ * The default UI for JHelpContentViewer.
+ *
+ * @author Eduardo Pelegri-Llopart
+ * @author Richard Gregor
+ * @version   1.57     10/30/06
+ */
+
+public class BasicContentViewerUI extends HelpContentViewerUI
+implements HelpModelListener, TextHelpModelListener, HyperlinkListener, PropertyChangeListener, Serializable {
+    // Suggestion: Refactor the class and remove the menu bar and the
+    //		HTML viewer into subclasses. This would allow easier
+    //		replacement of both components to
+    //
+    protected JHelpContentViewer theViewer;
+    
+    private static Dimension PREF_SIZE = new Dimension(200, 300);
+    private static Dimension MIN_SIZE = new Dimension(80, 80);
+    
+    private JEditorPane html;
+    private JViewport vp;
+    
+    private Hashtable registry;
+    private boolean loadingURL;
+    private TextHelpModelEvent pendingHighlightsEvent;
+    
+    public static ComponentUI createUI(JComponent x) {
+        debug("createUI");
+        return new BasicContentViewerUI((JHelpContentViewer) x);
+    }
+    
+    public BasicContentViewerUI(JHelpContentViewer b) {
+        debug("createUI - sort of");
+    }
+    
+    public void setEditorKit(String type, EditorKit kit) {
+        debug("setEditorKit("+type+", "+kit+")");
+        if (registry == null) {
+            registry = new Hashtable(3);
+        }
+        registry.put(type, kit);
+        if (html != null) {
+            debug("  type: "+type);
+            debug("  kit: "+kit);
+            html.setEditorKitForContentType(type, kit);
+            if (debug)
+                debug("  kit got: "+html.getEditorKitForContentType(type));
+        }
+    }
+    
+    /**
+     * Subclass of JEditorPane that uses the JHelpContentViewer type registry.
+     */
+    
+    class JHEditorPane extends JEditorPane {
+        private Hashtable typeHandlers;
+        
+        public EditorKit getEditorKitForContentType(String type) {
+            if (typeHandlers == null) {
+                typeHandlers = new Hashtable(3);
+            }
+            EditorKit k = (EditorKit) typeHandlers.get(type);
+            if (k == null) {
+                k = theViewer.createEditorKitForContentType(type);
+                if (k != null) {
+                    setEditorKitForContentType(type, k);
+                    typeHandlers.put(type, k);
+                }
+            }
+            if (k == null) {
+                k = super.getEditorKitForContentType(type);
+                if (k != null) {
+                    typeHandlers.put(type, k);
+                }
+            }
+            return k;
+        }
+        
+    }
+    
+       
+    public void installUI(JComponent c) {
+        debug("installUI");
+        theViewer = (JHelpContentViewer)c;
+        theViewer.setLayout(new BorderLayout());
+        
+        // listen to property changes...
+        theViewer.addPropertyChangeListener(this);
+        
+        TextHelpModel model = theViewer.getModel();
+        if (model != null) {
+            // listen to id changes...
+            model.addHelpModelListener(this);
+            // listen to highlight changes...
+            model.addTextHelpModelListener(this);
+        }
+        
+        html = new JHEditorPane();
+        html.addPropertyChangeListener(this);
+        html.getAccessibleContext().setAccessibleName(HelpUtilities.getString(HelpUtilities.getLocale(html), "access.contentViewer"));
+        html.setEditable(false);
+        html.addHyperlinkListener(this);
+
+	// if the model has a current URL then set it
+	if (model != null) {
+	    URL url = model.getCurrentURL();
+	    if (url != null) {
+		try {
+		    html.setPage(url);
+		} catch (IOException ex) {
+		    // just igonore it
+		}
+	    }
+	}
+
+        JScrollPane scroller = new JScrollPane();
+        scroller.setBorder(new BevelBorder(BevelBorder.LOWERED, Color.white,
+        Color.gray));
+        vp = scroller.getViewport();
+        vp.add(html);
+        vp.setBackingStoreEnabled(true);
+        
+        theViewer.add("Center", scroller);
+        loadingURL = false;
+        pendingHighlightsEvent = null;
+    }
+    
+    public void uninstallUI(JComponent c) {
+        debug("uninstallUI");
+        JHelpContentViewer viewer = (JHelpContentViewer) c;
+        viewer.removePropertyChangeListener(this);
+        html.removePropertyChangeListener(this);
+        TextHelpModel model = viewer.getModel();
+        if (model != null) {
+            model.removeHelpModelListener(this);
+            model.removeTextHelpModelListener(this);
+        }
+        viewer.setLayout(null);
+        viewer.removeAll();
+    }
+    
+    public Dimension getPreferredSize(JComponent c) {
+        return PREF_SIZE;
+    }
+    
+    public Dimension getMinimumSize(JComponent c) {
+        return MIN_SIZE;
+    }
+    
+    public Dimension getMaximumSize(JComponent c) {
+        // This doesn't seem right. But I'm not sure what to do for now
+        return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
+    }
+    
+    public void idChanged(HelpModelEvent e) {
+        ID id = e.getID();
+        URL url = e.getURL();
+        TextHelpModel model = theViewer.getModel();
+        debug("idChanged("+e+")");
+        debug("  = " + id + " " + url);
+        debug("  my helpModel: "+model);
+        
+        model.setDocumentTitle(null);
+        
+        // HERE - REMIND - event should be generated after visit
+        // with the title already in there - epll.
+        try {
+            Highlighter h = html.getHighlighter();
+            debug("removeAllHighlights");
+            h.removeAllHighlights();
+            try {
+                loadingURL = true;
+                html.setPage(url);
+            } catch (Exception ex) {
+                loadingURL = false;
+                // IGNORE FOR EA2 --- !! - epll
+            }
+            debug("html current EditorKit is: "+html.getEditorKit());
+            debug("html current ContentType is: "+html.getContentType());
+        } catch (Exception e3) {
+            // e.g. and incorrect URL will generate a nullexception!!
+            // ignore
+            debug("Exception geneartated");
+        }
+        debug("done with idChanged");
+    }
+    
+    private void rebuild() {
+        debug("rebuild");
+        TextHelpModel model = theViewer.getModel();
+        if (model == null) {
+            debug("rebuild-end: model is null");
+            return;
+        }
+        // The model has changed. I'll need to clear the HTML viewer and
+        // put in the home page
+        Highlighter h = html.getHighlighter();
+        debug("removeAllHighlights");
+        h.removeAllHighlights();
+        HelpSet hs = model.getHelpSet();
+        // for glossary - not set homeID page - glossary is not synchronized
+        if(theViewer.getSynch()){
+            try {
+                Map.ID homeID = hs.getHomeID();
+                Locale locale = hs.getLocale();
+                String name = HelpUtilities.getString(locale, "history.homePage");
+                model.setCurrentID(homeID, name, (JHelpNavigator)null);
+                html.setPage(model.getCurrentURL());
+            } catch (Exception e) {
+                // ignore
+            }
+        }
+        debug("rebuild-end");
+    }
+    
+    public void propertyChange(PropertyChangeEvent event) {
+        debug("propertyChange: " + event.getPropertyName() + "\n\toldValue:" + event.getOldValue() + "\n\tnewValue:" + event.getNewValue());
+        
+        if (event.getSource() == theViewer) {
+            String changeName = event.getPropertyName();
+            if (changeName.equals("helpModel")) {
+                TextHelpModel oldModel = (TextHelpModel) event.getOldValue();
+                TextHelpModel newModel = (TextHelpModel) event.getNewValue();
+                if (oldModel != null) {
+                    oldModel.removeHelpModelListener(this);
+                    oldModel.removeTextHelpModelListener(this);
+                }
+                if (newModel != null) {
+                    newModel.addHelpModelListener(this);
+                    newModel.addTextHelpModelListener(this);
+                }
+                rebuild();
+            } else if (changeName.equals("font")) {
+                debug("font changed");
+                Font newFont = (Font)event.getNewValue();
+                EditorKit ek = html.getEditorKit();
+                if (ek instanceof HTMLEditorKit) {
+                    
+                    StringBuffer buf = new StringBuffer(60);
+                    buf.append("body { font: ");
+                    buf.append(newFont.getSize()).append("pt ");
+                    if (newFont.isBold()) {
+                        buf.append("bold ");
+                    }
+                    if (newFont.isItalic()) {
+                        buf.append("italic ");
+                    }
+                    buf.append('"').append(newFont.getFamily()).append('"');
+                    buf.append(" }");
+                    String cssData = buf.toString();
+                        
+                    StyleSheet styleSheet;
+                    
+                    /* Update the default style sheet: */
+                    styleSheet = ((HTMLEditorKit) ek).getStyleSheet();
+                    styleSheet.addRule(cssData);
+                    
+                    /*
+                     * Update the current document's style sheet, thus forcing
+                     * the view to be refreshed:
+                     */
+                    styleSheet = ((HTMLDocument) html.getDocument()).getStyleSheet();
+                    styleSheet.addRule(cssData);
+                }
+            }else if (changeName.equals("clear")) {
+                html.setText("");
+            }else if (changeName.equals("reload")) {
+		URL url = html.getPage();
+		if (url != null) {
+		    try {
+			html.setPage(url);
+		    } catch (IOException ex) {
+			// just igonore it
+		    }
+		}
+            }
+        } else if (event.getSource() == html) {
+            String changeName = event.getPropertyName();
+            if (changeName.equals("page")) {
+                debug("page finished loading");
+                loadingURL = false;
+                if (pendingHighlightsEvent != null) {
+                    debug("Loading the highlights now");
+                    highlightsChanged(pendingHighlightsEvent);
+                    pendingHighlightsEvent = null;
+                }
+                Document doc = html.getDocument();
+                String title = (String)doc.getProperty(Document.TitleProperty);
+                TextHelpModel model = theViewer.getModel();
+                model.setDocumentTitle(title);
+                
+                // Propogate this to property listeners of the ContentViewer.
+                // Can't acutally send the real thing because Objects and
+                // Strings aren't supported.
+                theViewer.firePropertyChange(event.getPropertyName(),
+                false, true);
+            }
+        }
+    }
+    
+    /**
+     * Notification of a change relative to a
+     * hyperlink.
+     */
+    public void hyperlinkUpdate(HyperlinkEvent e) {
+        if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
+            // If in a frame do something different
+            if (e instanceof HTMLFrameHyperlinkEvent) {
+                ((HTMLDocument)html.getDocument()).processHTMLFrameHyperlinkEvent((HTMLFrameHyperlinkEvent)e);
+            } else {
+                // Not a frame
+                linkActivated(e.getURL());
+            }
+        }
+    }
+    
+    /**
+     * Follows the reference in an
+     * link.  The given url is the requested reference.
+     * By default this calls <a href="#setPage">setPage</a>,
+     * and if an exception is thrown the original previous
+     * document is restored and a beep sounded.  If an
+     * attempt was made to follow a link, but it represented
+     * a malformed url, this method will be called with a
+     * null argument.
+     *
+     * @param u the URL to follow
+     */
+    protected void linkActivated(URL u) {
+        debug("linkActivated - URL=" + u );
+        Cursor c = html.getCursor();
+        Cursor waitCursor = Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR);
+        html.setCursor(waitCursor);
+        // workaround for bug #418959
+        // if there is an anchor make sure the file doesn't end in "/" or "\"
+        // if it does then get the current file name and append the ref
+        String ref = u.getRef();
+        if (ref != null) {
+            String file = u.getFile();
+            if (file.endsWith("/") || file.endsWith("\\")) {
+                u = html.getPage();
+                debug("current u=" + u);
+                file = u.getFile();
+                debug("file=" + file);
+                try {
+                    u = new URL(u.getProtocol(), u.getHost(),
+                    u.getPort(), file + "#" + ref);
+                } catch (MalformedURLException e2) {
+                    return;
+                }
+                debug("new u=" + u);
+            }
+        }
+        SwingUtilities.invokeLater(new PageLoader(u, c));
+    }
+    
+    /**
+     * Temporary class that loads synchronously (although
+     * later than the request so that a cursor change
+     * can be done).
+     */
+    class PageLoader implements Runnable {
+        String title = null;
+        PageLoader(URL u, Cursor c) {
+            url = u;
+            cursor = c;
+        }
+        
+        public void run() {
+            if (url == null) {
+                // restore the original cursor
+                html.setCursor(cursor);
+                
+                RepaintManager.currentManager(html).markCompletelyDirty(html);
+            } else {
+                Document doc= html.getDocument();
+                //String title;
+                try {
+                    html.setPage(url);
+                    loadingURL = true;
+                    doc = html.getDocument();
+                    title = (String)doc.getProperty(Document.TitleProperty);                    
+                    String anchor = url.getRef();
+                    //if the title is not known (Hyperlink without anchor activated) parse title
+                    if(title == null)
+                        title = findTitle(url);
+                    //in case there is an anchor append it to the title
+                    if(anchor != null)
+                        title = title + "-" + anchor;
+                    TextHelpModel model = theViewer.getModel();
+                    model.setDocumentTitle(title);
+                    ID id = model.getHelpSet().getCombinedMap().getIDFromURL(url);
+                    if (id != null) {
+                        try {
+                            model.setCurrentID(id,title, (JHelpNavigator)null);
+                        } catch (InvalidHelpSetContextException ex) {
+                            model.setCurrentURL(url, title,(JHelpNavigator)null);
+                        }
+                    } else {
+                        model.setCurrentURL(url, title, (JHelpNavigator)null);
+                    }
+                } catch (IOException ioe) {
+                    loadingURL = false;
+                    html.setDocument(doc);
+                    html.getToolkit().beep();
+                } finally {
+                    // schedule the cursor to revert after
+                    // the paint has happended.
+                    url = null;
+                    SwingUtilities.invokeLater(this);
+                }
+            }
+        }
+        
+        URL url;
+        Cursor cursor;
+        
+        /**
+         * Finds the title of HTML document on given URL
+         *
+         * @param url The URL of HTML file
+         * @return The title of the document
+         */
+        private String findTitle(URL url){
+            HTMLEditorKit.ParserCallback callback;
+            try{
+                URLConnection conn = url.openConnection();
+                Reader rd = new InputStreamReader(conn.getInputStream());                
+                ParserDelegator parser = new ParserDelegator();
+                callback = new Callback();
+                parser.parse(rd,callback,true);
+            }catch (Exception exp){
+                System.err.println(exp);
+            }
+            return title;
+            
+        }
+        
+        /**
+         * Class provided the parser callback
+         */
+        class Callback extends HTMLEditorKit.ParserCallback{
+            boolean wasTitle = false;
+            
+            public void handleStartTag(HTML.Tag t, MutableAttributeSet a, int pos){
+                if(t.equals(HTML.Tag.TITLE)){
+                    wasTitle = true;
+                }
+            }
+            public void handleText(char[] data, int pos){
+                if(wasTitle){
+                    title = new String(data);
+                    wasTitle = false;
+                }
+            }
+            
+        }
+    }
+    
+    
+    
+    /**
+     * Determines if highlights have changed.
+     * Collects all the highlights and marks the presentation.
+     *
+     * @param e The TextHelpModelEvent.
+     */
+    public void highlightsChanged(TextHelpModelEvent e) {
+        debug("highlightsChanged "+e);
+        
+        // if we're loading this url this event will need to wait
+        // until we're notified that the page has finished loaded.
+        // we could wait(), but that would prevent the execution of
+        // other events in this thread. Instead preserve the
+        // TextHelpModelEvent and recall this method when the notification
+        // occurs.
+        if (loadingURL) {
+            debug("Humm. loadingURL wait a little");
+            pendingHighlightsEvent = e;
+            return;
+        }
+        
+        Highlighter h = html.getHighlighter();
+        debug1("removeAllHighlights");
+        h.removeAllHighlights();
+        
+        TextHelpModel m = (TextHelpModel) e.getSource();
+        TextHelpModel.Highlight highlights[] = m.getHighlights();
+        
+        Highlighter.HighlightPainter p =
+        new DefaultHighlighter.DefaultHighlightPainter(html.getSelectionColor());
+        for (int i=0; i<highlights.length; i++) {
+            int pos0 = highlights[i].getStartOffset();
+            int pos1 = highlights[i].getEndOffset();
+            debug("  highlight: "+pos0+", "+pos1);
+            try {
+                h.addHighlight(pos0, pos1, p);
+                
+                // scroll to the first position
+                if (i == 0) {
+                    Runnable callScrollToPosition = new ScrollToPosition(html,
+                    pos1);
+                    SwingUtilities.invokeLater(callScrollToPosition);
+                }
+            } catch (BadLocationException bl) {
+                debug("badLocationExcetpion thrown - " + bl);
+            }
+        }
+        RepaintManager.currentManager(html).markCompletelyDirty(html);
+    }
+    
+    private class ScrollToPosition implements Runnable {
+        private int pos;
+        private JEditorPane html;
+        
+        public ScrollToPosition(JEditorPane html, int pos) {
+            this.html = html;
+            this.pos = pos;
+        }
+        
+        public void run() {
+            try {
+                Rectangle rec = html.modelToView(pos);
+                if (rec != null) {
+                    html.scrollRectToVisible(rec);
+                }
+            } catch (BadLocationException bl) {
+            }
+        }
+    }
+    
+    /**
+     * For printf debugging.
+     */
+    private final static boolean debug = false;
+    private static void debug(String str) {
+        if (debug) {
+            System.out.println("BasicContentViewerUI: " + str);
+        }
+    }
+    private final static boolean debug1 = false;
+    private static void debug1(String str) {
+        if (debug1) {
+            System.out.println("BasicContentViewerUI: " + str);
+        }
+    }
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicCursorFactory.java b/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicCursorFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..34967be9e893a316667bbc843910fa8dffb7fd3e
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicCursorFactory.java
@@ -0,0 +1,195 @@
+/*
+ * @(#)BasicCursorFactory.java	1.11 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help.plaf.basic;
+
+import java.io.*;
+import javax.swing.ImageIcon;
+import java.awt.Cursor;
+import java.awt.Dimension;
+import java.awt.Image;
+import java.awt.Point;
+import java.awt.Toolkit;
+import java.awt.image.BufferedImage;
+import java.util.ResourceBundle;
+import java.util.MissingResourceException;
+import java.util.PropertyResourceBundle;
+
+/**
+ * Factory object that can vend cursors appropriate for the basic L & F.
+ * <p>
+ *
+ * @version 1.11	10/30/06
+ * @author Roger D. Brinkley
+ */
+public class BasicCursorFactory {
+    private static Cursor onItemCursor;
+    private static Cursor dndCursor;
+    private static BasicCursorFactory theFactory;
+
+    /**
+     * Returns the OnItem cursor.
+     */
+    public static Cursor getOnItemCursor() {
+	debug ("getOnItemCursor");
+	if (theFactory == null) {
+	    theFactory = new BasicCursorFactory();
+	}
+	if (onItemCursor == null) {
+	    onItemCursor = theFactory.createCursor("OnItemCursor");
+	}
+	return onItemCursor;
+    }
+
+    /**
+     * Returns the DnDCursor.
+     */
+    public static Cursor getDnDCursor(){
+        debug("getDnDCursor");
+        if (theFactory == null) {
+	    theFactory = new BasicCursorFactory();
+	}
+	if (dndCursor == null) {
+	    dndCursor = theFactory.createCursor("DnDCursor");
+	}
+	return dndCursor;
+    }
+    
+    private Cursor createCursor(String name) {
+ 	String gifFile = null;
+	String hotspot = null;
+	ImageIcon icon;
+	Point point;
+
+	debug("CreateCursor for " + name);
+
+	// Get the Property file
+	InputStream is = getClass().getResourceAsStream("images/" + name + ".properties");
+	if (is == null) {
+	    debug(getClass().getName() + "/" + 
+			       "images/" + name + ".properties" + " not found.");
+	    return null;
+	}
+	try {
+	    ResourceBundle resource = new PropertyResourceBundle(is);
+	    gifFile = resource.getString("Cursor.File");
+	    hotspot = resource.getString("Cursor.HotSpot");
+	} catch (MissingResourceException e) {
+	    debug(getClass().getName() + "/" + 
+			       "images/" + name + ".properties" + " invalid.");
+	    return null;
+	} catch (IOException e2) {
+	    debug(getClass().getName() + "/" + 
+			       "images/" + name + ".properties" + " invalid.");
+	    return null;
+	}
+
+	// Create the icon
+	byte[] buffer = null;
+	try {
+	    /* Copies resource into a byte array.  This is
+	     * necessary because several browsers consider
+	     * Class.getResource a security risk because it
+	     * can be used to load additional classes.
+	     * Class.getResourceAsStream returns raw
+	     * bytes, which JH can convert to an image.
+	     */
+	    InputStream resource = 
+		getClass().getResourceAsStream(gifFile);
+	    if (resource == null) {
+		debug(getClass().getName() + "/" + 
+				   gifFile + " not found.");
+		return null; 
+	    }
+	    BufferedInputStream in = 
+		new BufferedInputStream(resource);
+	    ByteArrayOutputStream out = 
+		new ByteArrayOutputStream(1024);
+	    buffer = new byte[1024];
+	    int n;
+	    while ((n = in.read(buffer)) > 0) {
+		out.write(buffer, 0, n);
+	    }
+	    in.close();
+	    out.flush();
+	    
+	    buffer = out.toByteArray();
+	    if (buffer.length == 0) {
+		debug("warning: " + gifFile + 
+				   " is zero-length");
+		return null;
+	    }
+	} catch (IOException ioe) {
+	    debug(ioe.toString());
+	    return null;
+	}
+
+	icon = new ImageIcon(buffer);
+
+	// create the point
+	int k = hotspot.indexOf(',');
+	point = new Point(Integer.parseInt(hotspot.substring(0,k)),
+			  Integer.parseInt(hotspot.substring(k+1)));
+	
+	debug ("Toolkit fetching cursor");
+	try {
+            
+            Image image = icon.getImage();
+            int width = icon.getIconWidth();
+            int height = icon.getIconHeight();
+            
+            Toolkit toolkit = Toolkit.getDefaultToolkit();
+            Dimension d = toolkit.getBestCursorSize(width, height);
+
+            if ((d.width > width) || (d.height > height)) {
+                try {
+                    Image bimage = new BufferedImage(d.width, d.height, BufferedImage.TYPE_INT_ARGB);
+                    bimage.getGraphics().drawImage(icon.getImage(), 0, 0, icon.getImageObserver());
+                    image = bimage;
+                } catch (Exception ex) {
+                }
+            }
+            
+	    return toolkit.createCustomCursor(image, point, name);
+            
+	} catch (NoSuchMethodError err) {
+	    //	    return Cursor.getPredefinedCursor(Cursor.HAND_CURSOR);
+	    return null;
+	}
+    }
+
+    /**
+     * For printf debugging.
+     */
+    private static final boolean debug = false;
+    private static void debug(String str) {
+        if (debug) {
+            System.out.println("BasicCursorFactory: " + str);
+        }
+    }
+
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicFavoritesCellRenderer.java b/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicFavoritesCellRenderer.java
new file mode 100644
index 0000000000000000000000000000000000000000..6824c6cdb12182fd61abad579391827f5e4bd495
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicFavoritesCellRenderer.java
@@ -0,0 +1,93 @@
+/*
+ * @(#)BasicFavoritesCellRenderer.java	1.4 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+
+package javax.help.plaf.basic;
+
+/**
+ * Cell Renderer for the favorites UI.
+ *
+ * @author Richard Gregor
+ * @version	1.4	10/30/06
+ */
+import javax.swing.*;
+import javax.swing.tree.DefaultTreeCellRenderer;
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.TreeNode;
+import java.awt.*;
+import java.net.URL;
+import java.util.Locale;
+import javax.help.TOCItem;
+import javax.help.Map;
+import javax.help.HelpUtilities;
+import javax.help.Map.ID;
+import javax.help.FavoritesItem;
+
+public class BasicFavoritesCellRenderer extends DefaultTreeCellRenderer {
+    
+    public Component getTreeCellRendererComponent(JTree tree, Object value,
+    boolean sel,
+    boolean expanded,
+    boolean leaf, int row,
+    boolean hasFocus) {
+        
+        FavoritesItem item;
+        
+        Object o = ((DefaultMutableTreeNode)value).getUserObject();
+        String stringValue = "";
+                
+        item = (FavoritesItem) o;
+        if (item != null) {
+            stringValue = item.getName();
+        }
+        
+        // Set the locale of this if there is a lang value
+        if (item != null) {
+            Locale locale = item.getLocale();
+            if (locale != null) {
+                setLocale(locale);
+            }
+        }
+        
+        setText(stringValue);
+        
+        if (sel)
+            setForeground(getTextSelectionColor());
+        else
+            setForeground(getTextNonSelectionColor());
+        selected = sel;
+        
+        if(leaf)
+            setIcon(getDefaultLeafIcon());
+        else if(expanded)
+            setIcon(getDefaultOpenIcon());
+        else
+            setIcon(getDefaultClosedIcon());        
+       
+        return this;
+    }    
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicFavoritesNavigatorUI.java b/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicFavoritesNavigatorUI.java
new file mode 100644
index 0000000000000000000000000000000000000000..eb08a014056ab6f528ae83da6efc9c11393e833a
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicFavoritesNavigatorUI.java
@@ -0,0 +1,1558 @@
+/*
+ * @(#)BasicFavoritesNavigatorUI.java	1.17 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help.plaf.basic;
+
+import javax.help.*;
+import javax.help.plaf.HelpNavigatorUI;
+import javax.help.plaf.HelpUI;
+import javax.help.event.HelpModelListener;
+import javax.help.event.HelpModelEvent;
+import java.util.EventObject;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+import java.util.Locale;
+import java.util.HashMap;
+import javax.swing.*;
+import javax.swing.plaf.ComponentUI;
+import javax.swing.tree.*;
+import javax.swing.event.*;
+import java.awt.*;
+import java.awt.event.*;
+import java.io.Reader;
+import java.io.Serializable;
+import java.net.URL;
+import java.net.URLConnection;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.awt.event.ComponentEvent;
+import javax.help.Map.ID;
+import java.text.Collator;
+import java.text.RuleBasedCollator;
+import java.net.MalformedURLException;
+import java.util.HashSet;
+import javax.help.event.HelpSetListener;
+import javax.help.event.HelpSetEvent;
+import java.awt.Cursor;
+import java.awt.image.BufferedImage;
+import java.awt.geom.Rectangle2D.Float;
+import java.awt.geom.Rectangle2D;
+import java.awt.geom.AffineTransform;
+import java.awt.datatransfer.*;
+import java.awt.dnd.*;
+import java.awt.dnd.peer.*;
+import java.io.IOException;
+
+/**
+ * The default UI for JHelpNavigator of type Favorites
+ *
+ * @author Richard Gregor
+ * @version	1.17	10/30/06
+ */
+
+public class BasicFavoritesNavigatorUI extends HelpNavigatorUI
+implements HelpModelListener, TreeSelectionListener, HelpSetListener,
+PropertyChangeListener, TreeModelListener, Serializable {
+    
+    protected JHelpFavoritesNavigator favorites;
+    protected JScrollPane sp;
+    protected FavoritesNode topNode;
+    protected JTree tree;
+    private   String contentTitle;
+    protected RuleBasedCollator rbc;
+    protected String oldText;
+    protected DefaultMutableTreeNode currentFindNode;
+    protected Action addAction;
+    protected Action removeAction;
+    protected Action cutAction;
+    protected Action pasteAction;
+    protected Action copyAction;
+    protected Action folderAction;
+    protected JPopupMenu popup;
+    
+    private   HashMap dataMap = new HashMap();
+    // node wich will contain parsed favorites data
+    private   FavoritesNode favNode = null;
+    // node which contents will be saved
+    private   FavoritesNode rootNode = null;
+    private   Locale locale = null;
+    private   FavoritesNode selectedNode = null;
+    private   FavoritesItem selectedItem = null;
+    private   TreePath selectedTreePath = null;
+    private   Map.ID selectedID = null;
+    private   JMenuItem newFolderMI = null;
+    private   JMenuItem addMI = null;
+    private   JSeparator separatorMI = null;
+    private   JMenuItem cutMI = null;
+    private   JMenuItem copyMI = null;
+    private   JMenuItem pasteMI = null;
+    private   JMenuItem removeMI = null;
+    private   HashMap hsMap = null;
+    //HasMap with visible node from favNode as key and its related node from rootNode as a value
+    private   HashMap connections = new HashMap();
+    /**
+     * Vector of nodes used in CutAction
+     */
+    private   Vector nodeClipboard = new Vector();
+
+    static private boolean on1dot3 = false;
+
+    static {
+        try {
+            // Test if method introduced in 1.3 or greater is available.
+            Class klass = Class.forName("javax.swing.InputVerifier");
+            on1dot3 = (klass != null);
+        } catch (ClassNotFoundException e) {
+            on1dot3 = false;
+        }
+    }
+
+    
+    public static ComponentUI createUI(JComponent x) {
+        return new BasicFavoritesNavigatorUI((JHelpFavoritesNavigator) x);
+    }
+    /**
+     * Creates BasicFavoritesUI for JHelpFavoritesNavigator
+     */
+    public BasicFavoritesNavigatorUI(JHelpFavoritesNavigator b) {
+        ImageIcon icon = getImageIcon(b.getNavigatorView());
+        if (icon != null) {
+            setIcon(icon);
+	} else {
+            setIcon(UIManager.getIcon("FavoritesNav.icon")); 
+	}
+    }
+    
+    public void installUI(JComponent c) {
+        debug("installUI");
+        
+        locale = HelpUtilities.getLocale(c);
+        addAction = new AddAction();
+        removeAction = new RemoveAction();
+        folderAction = new FolderAction();
+        favorites = (JHelpFavoritesNavigator)c;
+        HelpModel model = favorites.getModel();
+        
+        favorites.setLayout(new BorderLayout());
+        favorites.addPropertyChangeListener(this);
+        if (model != null) {
+            model.addHelpModelListener(this); // for our own changes
+            model.addPropertyChangeListener(this); // for HelpSet change
+            HelpSet helpSet = model.getHelpSet();
+            if(helpSet != null)
+                helpSet.addHelpSetListener(this);
+        }
+        
+	topNode = new FavoritesNode(new FavoritesItem("Favorites"));
+	if (on1dot3) {
+	    // Use drag and drop if available
+	    tree = new FavoritesTree(topNode);
+	} else {
+	    tree = new JTree(topNode);
+	}
+	tree.setEditable(true);
+	tree.addMouseListener(new PopupListener());
+	
+	cutAction = new CutAction();
+	copyAction = new CopyAction();
+	pasteAction = new PasteAction();
+	
+	popup = new JPopupMenu();
+	
+	newFolderMI = new JMenuItem((String)folderAction.getValue(folderAction.NAME));
+	newFolderMI.addActionListener(folderAction);
+	popup.add(newFolderMI);
+	
+	addMI = new JMenuItem((String)addAction.getValue(addAction.NAME));
+	addMI.addActionListener(addAction);
+	popup.add(addMI);
+
+	separatorMI = new JSeparator();
+	popup.add(separatorMI);
+	
+	cutMI = new JMenuItem((String)cutAction.getValue(cutAction.NAME));
+	cutMI.addActionListener(cutAction);
+	cutMI.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X,java.awt.Event.CTRL_MASK));
+	popup.add(cutMI);
+	
+	copyMI = new JMenuItem((String)copyAction.getValue(copyAction.NAME));
+	copyMI.addActionListener(copyAction);
+	copyMI.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C,java.awt.Event.CTRL_MASK));
+	popup.add(copyMI);
+	
+	pasteMI = new JMenuItem((String)pasteAction.getValue(pasteAction.NAME));
+	pasteMI.addActionListener(pasteAction);
+	pasteMI.setEnabled(false);
+	pasteMI.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_V,java.awt.Event.CTRL_MASK));
+	popup.add(pasteMI);
+	
+	removeMI = new JMenuItem((String) removeAction.getValue(removeAction.NAME));
+	removeMI.addActionListener(removeAction);
+	
+	popup.add(removeMI);
+        
+        tree.getModel().addTreeModelListener(this);
+        tree.addTreeSelectionListener(this);
+        
+        TreeSelectionModel tsm = tree.getSelectionModel();
+        tsm.addTreeSelectionListener(this);
+        
+        tree.setShowsRootHandles(true);
+        tree.setRootVisible(false);
+        
+        setCellRenderer(favorites.getNavigatorView(), tree);
+ 
+        sp = new JScrollPane();
+        sp.getViewport().add(tree);
+        
+        favorites.add("Center", sp);
+        
+        reloadData();
+    }
+    
+    /**
+     * Sets the desired cell renderer on this tree.  This is exposed for redefinition
+     * by subclases.
+     */
+    protected void setCellRenderer(NavigatorView view, JTree tree) {
+        tree.setCellRenderer(new BasicFavoritesCellRenderer());
+    }
+    
+    public void uninstallUI(JComponent c) {
+        debug("uninstallUI");
+        HelpModel model = favorites.getModel();
+        
+        favorites.removePropertyChangeListener(this);
+        TreeSelectionModel tsm = tree.getSelectionModel();
+        tsm.removeTreeSelectionListener(this);
+        favorites.setLayout(null);
+        favorites.removeAll();
+        
+        if (model != null) {
+            model.removeHelpModelListener(this);
+        }
+        
+        favorites = null;
+    }
+    
+    public Dimension getPreferredSize(JComponent c) {
+        
+        return new Dimension(200,100);
+        
+    }
+    
+    public Dimension getMinimumSize(JComponent c) {
+        return new Dimension(100,100);
+    }
+    
+    public Dimension getMaximumSize(JComponent c) {
+        return new Dimension(Short.MAX_VALUE, Short.MAX_VALUE);
+    }
+    
+    
+    private void reloadData() {
+        debug("reloadData");
+        
+        //needs refactoring - sholudn't parse each time!!! - only once
+        
+        if (favorites.getModel() == null) {
+            return;
+        }
+        
+        // remove all children
+        topNode.removeAllChildren();
+        
+        FavoritesView view = (FavoritesView) favorites.getNavigatorView();
+        
+        if (view == null) {
+            return;
+        }
+
+        favNode = view.getDataAsTree();
+        rootNode = favNode.getDeepCopy();
+
+        classifyNode(favNode);
+        while (favNode.getChildCount() > 0) {
+	    // this looks strange but as you add a child to the top node
+	    // it removes the child from the favNode so the getFirstChild
+	    // will always get the first child
+            topNode.add((DefaultMutableTreeNode)favNode.getFirstChild());
+        }
+        
+        // reload the tree data
+        ((DefaultTreeModel)tree.getModel()).reload();
+        
+        setVisibility(topNode);        
+        
+    }
+    
+    /**
+     * Classifies the node. Determines wheter child will be visible or not according to node's HelpSet.
+     * Hides node without children when its HelpSet is not loaded
+     *
+     * @param node The FavoritesNode
+     */
+    private void classifyNode(FavoritesNode node){
+        debug("classifyNode");
+        
+        if(node == null)
+            return;
+        
+        HelpModel model = favorites.getModel();
+        if(model == null){
+            node.removeAllChildren();
+            return;
+        }
+        HelpSet masterHelpSet = model.getHelpSet();
+        if(masterHelpSet == null){
+            node.removeAllChildren();
+            return;
+        }
+        hsMap = new HashMap();
+        hsMap.put(masterHelpSet.getTitle(), masterHelpSet);
+        
+        fillHelpSetTitles(masterHelpSet);
+        
+        // tags node's children wheter they are visible or not
+        classifyChildren(node);
+        
+    }
+    
+    /**
+     * Fills HashMap with actual HelpSets and their titles
+     *
+     * @param masterHelpSet The master HelpSet
+     */
+    private void fillHelpSetTitles(HelpSet masterHelpSet){
+        for(Enumeration helpSets = masterHelpSet.getHelpSets();helpSets.hasMoreElements();){
+            HelpSet hs = (HelpSet) helpSets.nextElement();
+            if(hs != null){
+                hsMap.put(hs.getTitle(), hs);
+                debug(" fill title: "+hs.getTitle());
+                fillHelpSetTitles(hs);
+            }
+        }
+    }
+    
+    /**
+     * Classifies children of node
+     *
+     * @param node The FavoritesNode
+     */
+    private void classifyChildren(FavoritesNode node){
+        debug("classifyChildren: "+node);
+        
+        if(node == null)
+            return;
+        
+	boolean skipChild = true;
+
+        for(Enumeration children = node.preorderEnumeration();children.hasMoreElements();){
+            FavoritesNode chnode = (FavoritesNode)children.nextElement();
+
+	    // Skip the first entry because it is node and we don't need
+	    // to classify the node only it's children
+	    if (skipChild) {
+		skipChild = false;
+		continue;
+	    }
+
+	    // Add this child node to the root node. 
+
+	    // Make a copy of the child node for the rootNode 
+            FavoritesNode copy = chnode.getDeepCopy();
+
+	    // establish the connection between the chnode and the copy
+            connections.put(chnode, copy);
+	    // properly connect it to the childs corresponding parent in the 
+	    // rootnode. 
+	    FavoritesNode rootParent = (FavoritesNode)connections.get(chnode.getParent());
+	    if (rootParent == null) {
+		rootParent = rootNode;
+	    }
+	    rootParent.add(copy);
+
+	    // Now on to seeing if the item
+            FavoritesItem item = (FavoritesItem)chnode.getUserObject();
+            debug("classify item: "+ item);
+            //shouldn't happen
+            if(item == null){
+                debug("item is null : fillDataMap");
+                continue;
+            }
+            String target = item.getTarget();
+            String hsTitle = item.getHelpSetTitle();
+            if(!hsMap.containsKey(hsTitle)){
+                if(chnode.getVisibleChildCount() == 0){
+                    if(item.emptyInitState() && item.isFolder()){
+                        debug("empty init state");
+                        continue;
+                    }
+                    //chnode.removeFromParent();
+                    item.setVisible(false);
+                    continue;
+                }
+            }
+            
+            if(target == null){
+                debug("target is null:fillDataMap");
+                continue;
+            }
+            
+            Map.ID id = null;
+            try{
+                id = Map.ID.create(target, (HelpSet)hsMap.get(hsTitle));
+            }catch(BadIDException ep){
+                debug(ep.getMessage());
+                continue;
+            }
+            
+            debug("put to the dataMap: "+item);
+            dataMap.put(item,id);
+        }
+        
+        //clear node
+	Vector toRemove = new Vector();
+	Enumeration nodesToRem = node.breadthFirstEnumeration();
+	while(nodesToRem.hasMoreElements()) {
+	    FavoritesNode fn = (FavoritesNode)nodesToRem.nextElement();
+            if(!fn.isVisible()){
+		debug ("remove node:" +(FavoritesItem)fn.getUserObject());
+		toRemove.addElement(fn);
+            }
+	}
+	for (int i=0; i < toRemove.size(); i++) {
+	    debug("removing " +  toRemove.elementAt(i));
+	    try {
+		node.remove((DefaultMutableTreeNode) toRemove.elementAt(i));
+	    } catch (IllegalArgumentException iae) {
+		// ignore - supernode is already removed
+	    }
+        }
+        
+    }
+    
+    /**
+     * Expands entry path and entry itself( when entry is not empty) for specific id
+     *
+     * @param target The target of entry
+     */
+    
+    private void expand(String target){
+        debug("expand called");
+        //find all nodes with certain id
+        Enumeration nodes = findNodes(target).elements();
+        DefaultMutableTreeNode node = null;
+        
+        while(nodes.hasMoreElements()){
+            node = (DefaultMutableTreeNode)nodes.nextElement();
+            debug("expandPath :"+node);
+            if(node.getChildCount() > 0){
+                DefaultMutableTreeNode child =(DefaultMutableTreeNode) node.getFirstChild();
+                TreePath path = new TreePath(child.getPath());
+                tree.makeVisible(path);
+            }
+            else{
+                TreeNode[] treeNode = node.getPath();
+                TreePath path = new TreePath(treeNode);
+                //tree.scrollPathToVisible(path);
+                tree.makeVisible(path);
+            }
+        }
+    }
+    
+    /**
+     * Returns all nodes with certain id
+     *
+     * @param target The target of entry
+     *
+     */
+    private Vector findNodes(String target){
+        Enumeration nodes = topNode.preorderEnumeration();
+        DefaultMutableTreeNode node = null;
+        Vector nodeFound = new Vector();
+        
+        while(nodes.hasMoreElements()){
+            node = (DefaultMutableTreeNode)nodes.nextElement();
+            debug(" node :"+ node.toString());
+            if(node != null){
+                FavoritesItem favoritesItem = (FavoritesItem)node.getUserObject();
+                if(favoritesItem == null)
+                    debug("favoritesItem is null");
+                else{
+                    //Map.ID id = favoritesItem.getID();
+                    Map.ID id = (Map.ID)dataMap.get(favoritesItem);
+                    if(id != null){
+                        debug("id name :"+id.id);
+                        debug("target :"+target);
+                        Map.ID itemID = null;
+                        try{
+                            itemID = Map.ID.create(target,favorites.getModel().getHelpSet());
+                        }
+                        catch(BadIDException exp){
+                            System.err.println("Not valid ID :"+target );
+                            break;
+                        }
+                        if(id.equals(itemID))
+                            nodeFound.addElement(node);
+                    }
+                }
+            }
+        }
+        
+        return nodeFound;
+    }
+    
+    /**
+     * Collapses entry specified by id. If entry is empty collapses it's parent.
+     *
+     * @param target The target of entry
+     */
+    
+    private void collapse(String target){
+        Enumeration nodes = findNodes(target).elements();
+        DefaultMutableTreeNode node = null;
+        debug("collapse called");
+        
+        while(nodes.hasMoreElements()){
+            node = (DefaultMutableTreeNode)nodes.nextElement();
+            if(node.getChildCount() > 0){
+                TreeNode[] treeNode = node.getPath();
+                TreePath path = new TreePath(treeNode);
+                tree.collapsePath(path);
+                tree.collapseRow(tree.getRowForPath(path));
+            }
+            else{
+                DefaultMutableTreeNode parent =(DefaultMutableTreeNode) node.getParent();
+                TreePath path = new TreePath(parent.getPath());
+                tree.collapseRow(tree.getRowForPath(path));
+            }
+        }
+    }
+    
+    // Make all nodes visible
+    
+    private void setVisibility(DefaultMutableTreeNode node) {
+        tree.expandPath(new TreePath(node.getPath()));
+        if (! node.isLeaf()) {
+            int max = node.getChildCount();
+            for (int i=0; i<max; i++) {
+                setVisibility((DefaultMutableTreeNode)node.getChildAt(i));
+            }
+        }
+    }
+    
+    /**
+     * Processes and idChanged event. In this navigator works with url too.
+     *
+     * @param e The HelpModelEvent
+     */
+    
+    public void idChanged(HelpModelEvent e) {
+        debug("idChanged("+e+")");
+        
+        //next values
+        ID id = e.getID();
+        contentTitle = e.getHistoryName();
+        URL nurl = e.getURL();
+        String nURL = null;
+        if (nurl != null)
+            nURL = nurl.toExternalForm();
+        
+        //current values
+        ID currentID = null;
+        String currentURL = null;
+        String currentName = null;
+	FavoritesItem item = null;
+        
+        HelpModel helpModel = favorites.getModel();
+        
+        
+        if (e.getSource() != helpModel) {
+            debug("Internal inconsistency!");
+            debug("  "+e.getSource()+" != "+helpModel);
+            throw new Error("Internal error");
+        }
+        
+        TreePath s = tree.getSelectionPath();
+        if (s != null) {
+            Object o = s.getLastPathComponent();
+            // should require only a TreeNode
+            if (o instanceof DefaultMutableTreeNode) {
+                DefaultMutableTreeNode tn = (DefaultMutableTreeNode) o;
+                item = (FavoritesItem) tn.getUserObject();
+                if (item != null){
+                    currentID = (Map.ID) dataMap.get(item);
+                    currentURL = item.getURLSpec();
+                    currentName = item.getName();
+                }
+                if((currentName != null) && (currentName.equals(contentTitle))){
+                    if(currentID != null)
+                        if(currentID.equals(id))
+                            return;
+                    if(currentURL != null)
+                        if(currentURL.equals(nURL))
+                            return;
+                }
+            }
+        }
+        
+        DefaultMutableTreeNode node = null;        
+
+        node = findID(topNode, id);
+        if(node == null) {
+            node = findURL(topNode, nURL);
+	}
+
+        if (node == null) {
+            // node doesn't exist. Need to clear the selection.
+            tree.clearSelection();
+            return;
+        }
+        TreePath path = new TreePath(node.getPath());
+        tree.expandPath(path);
+        tree.setSelectionPath(path);
+        tree.scrollPathToVisible(path);
+    }
+    
+    private DefaultMutableTreeNode findID(DefaultMutableTreeNode node, ID id) {
+        debug("findID: ("+id+")");
+        debug("  node: "+node);
+        
+        // check on the id
+        if (id == null) {
+            return null;
+        }
+        FavoritesItem item = (FavoritesItem) node.getUserObject();
+        Map.ID  itemID = (Map.ID) dataMap.get(item);
+        if (itemID != null) {
+            ID testID = itemID;
+            debug("  testID: "+testID);
+            if (testID != null && testID.equals(id)) {
+                return node;
+            }
+        }
+        int size = node.getChildCount();
+        for (int i=0; i<size ; i++) {
+            DefaultMutableTreeNode tmp =
+            (DefaultMutableTreeNode) node.getChildAt(i);
+            DefaultMutableTreeNode test = findID(tmp, id);
+            if (test != null) {
+                return test;
+            }
+        }
+        return null;
+    }
+    /**
+     * Finds the subnode with certain url and name
+     */
+    private DefaultMutableTreeNode findURL(DefaultMutableTreeNode node, String urlSpec){
+        debug(" findURL: "+ urlSpec);
+        
+        if(urlSpec == null)
+            return null;
+        
+        for(Enumeration children = node.children(); children.hasMoreElements();){
+            DefaultMutableTreeNode child = (DefaultMutableTreeNode)children.nextElement();
+            FavoritesItem childItem = (FavoritesItem) child.getUserObject();
+            String childName = childItem.getName();
+            String childURL = childItem.getURLSpec();
+            if(urlSpec.equals(childURL))
+                return child;
+            else
+                findURL(child,urlSpec);
+        }
+        return null;
+    }
+    
+    /**
+     * Finds the subnode with certain id and name
+     */
+    
+    public void valueChanged(TreeSelectionEvent e) {
+        
+        selectedTreePath = e.getNewLeadSelectionPath();
+        if (selectedTreePath == null) {
+            selectedNode = null;
+            return;
+        }
+        selectedNode =
+        (FavoritesNode)selectedTreePath.getLastPathComponent();
+        if (selectedNode != null){
+            selectedItem = (FavoritesItem)selectedNode.getUserObject();
+            selectedID = (Map.ID)dataMap.get(selectedItem);
+        }
+        
+        HelpModel helpModel = favorites.getModel();
+	HelpSet hs = helpModel.getHelpSet();
+        
+        debug("ValueChanged: "+e);
+        debug("  model: "+helpModel);
+        if(helpModel == null)
+            return;
+        // send selected items into navigator
+        TreeItem[] items = null;
+        TreePath[] paths = tree.getSelectionPaths();
+        if (paths != null) {
+            removeAction.setEnabled(true);
+            items = new TreeItem[paths.length];
+            for (int i = 0; i < paths.length; i++) {
+                if (paths[i] != null) {
+                    DefaultMutableTreeNode node = (DefaultMutableTreeNode) paths[i].getLastPathComponent();
+		    FavoritesItem favItem = (FavoritesItem) node.getUserObject();
+		    // need to normalize this item so it looks like a real TreeItem
+		    try {
+			String target = favItem.getTarget();
+			if (target != null) {
+			    ID id = Map.ID.create(favItem.getTarget(), hs);
+			    favItem.setID(id);
+			}
+		    } catch (BadIDException ee) {
+		    }
+		    items[i] = (TreeItem) favItem;
+                }
+            }
+        }else{
+            removeAction.setEnabled(false);
+            pasteAction.setEnabled(false);
+            pasteMI.setEnabled(false);
+            return;
+        }
+        favorites.setSelectedItems(items);
+        
+        // change current id only if one item is selected
+        if (items != null && items.length == 1) {
+            FavoritesItem item = (FavoritesItem) items[0];
+            if (item != null) {
+                Map.ID itemID = (Map.ID) dataMap.get(item);
+                if(itemID != null){
+                    debug("itemID: "+itemID);
+                    try{
+                        // helpmodel.setCurrentID(item.getID());
+                        helpModel.setCurrentID(itemID, item.getName(), (JHelpNavigator)favorites);
+                    } catch (InvalidHelpSetContextException ex) {
+                        System.err.println("BadID: "+item.getID());
+                        return;
+                    }
+                }else{
+                    if(item.getURLSpec() != null){
+                        try{
+                            URL url = new URL(item.getURLSpec());
+                            helpModel.setCurrentURL(url,item.getName(),(JHelpNavigator)favorites);
+                        }catch(MalformedURLException ep){
+                            System.err.println(ep);
+                        }
+                    }
+                }
+            }
+        }
+    }
+    
+    public void propertyChange(PropertyChangeEvent event) {
+        debug("propertyChange: " + event.getSource() + " "  +
+        event.getPropertyName());
+        
+        if (event.getSource() == favorites) {
+            String changeName = event.getPropertyName();
+            if (changeName.equals("helpModel")) {
+                debug("model changed");
+                reloadData();
+                
+            } else  if (changeName.equals("font")) {
+                debug("Font change");
+                Font newFont = (Font)event.getNewValue();
+                tree.setFont(newFont);
+                RepaintManager.currentManager(tree).markCompletelyDirty(tree);
+            } else if(changeName.equals("expand")){
+                debug("Expand change");
+                expand((String)event.getNewValue());
+            } else if(changeName.equals("collapse")){
+                debug("Collapse change");
+                collapse((String)event.getNewValue());
+            } else if(changeName.equals("navigatorChange")){
+                debug("Navigator change");
+                tree.clearSelection();
+            }
+            
+            // changes to UI property?
+            
+        }else if (favorites != null){
+            if (event.getSource() == favorites.getModel()) {
+                String changeName = event.getPropertyName();
+                if( changeName.equals("helpSet")) {
+                    reloadData();
+                }
+            }
+        }
+    }
+    
+    public void helpSetAdded(HelpSetEvent ev){
+        debug("HelpSet added");
+        reloadData();
+    }
+    
+    public void helpSetRemoved(HelpSetEvent ev){
+        debug("HelpSet removed");
+        reloadData();
+    }
+    
+    /**
+     * Saves favorites to the file
+     */
+    public void saveFavorites(){
+        FavoritesView view = (FavoritesView)favorites.getNavigatorView();
+        view.saveFavorites(rootNode);
+    }
+    
+    public void treeStructureChanged(javax.swing.event.TreeModelEvent treeModelEvent) {
+        debug("tree structure changed");
+    }
+    
+    public void treeNodesInserted(javax.swing.event.TreeModelEvent treeModelEvent) {
+        debug("node inserted");
+        int place = -1;
+        FavoritesNode parent = (FavoritesNode) treeModelEvent.getTreePath().getLastPathComponent();
+        Object nodes[] = treeModelEvent.getChildren();
+        int[] indices = treeModelEvent.getChildIndices();
+        int firstIndex = indices[0];
+        debug("index first "+firstIndex);
+        int lastIndex = (indices.length + firstIndex) - 1;
+        FavoritesNode rootParent = (FavoritesNode)connections.get(parent);
+        if(rootParent == null)
+            rootParent = rootNode;
+        
+        debug("root parent "+rootParent);
+        //nodes were inserted into first place in parent
+        if(firstIndex == 0){
+            if(rootParent.getChildCount() == 0)
+                place = 0;
+            else{
+                for(Enumeration en = rootParent.children(); en.hasMoreElements();){
+                    FavoritesNode node = (FavoritesNode)en.nextElement();
+                    if(node.isVisible()){
+                        debug("is visible : "+node);
+                        place = rootParent.getIndex(node);
+                        break;
+                    }
+                }
+            }
+            //insert nodes in node place
+            if(place >= 0){
+                for(int j = nodes.length - 1; j >= 0; j--){
+                    FavoritesNode copy = ((FavoritesNode) nodes[j]).getDeepCopy();
+                    rootParent.insert((DefaultMutableTreeNode)copy,place);
+                    connections.put((FavoritesNode)nodes[j],copy);
+                }
+            }
+            
+        }else if (firstIndex > 0){
+            //find what is before
+            FavoritesNode nodeBefore = (FavoritesNode)parent.getChildAt(firstIndex - 1);
+            FavoritesNode rootNode = (FavoritesNode)connections.get(nodeBefore);
+            place = rootParent.getIndex(rootNode)+1;
+            for(int k = nodes.length - 1; k >= 0; k--){
+                FavoritesNode copyNode = ((FavoritesNode)nodes[k]).getDeepCopy();
+                rootParent.insert((DefaultMutableTreeNode)copyNode,place);
+                connections.put((FavoritesNode)nodes[k],copyNode);
+            }
+        }
+    }
+    
+    public void treeNodesRemoved(javax.swing.event.TreeModelEvent treeModelEvent) {
+        debug("nodes removed");
+        Object nodes[] = treeModelEvent.getChildren();
+        for(int i = 0; i < nodes.length; i++){
+            FavoritesNode originalNode = (FavoritesNode)nodes[i];
+            FavoritesNode remNode = (FavoritesNode)connections.get(originalNode);
+            if(remNode != null)
+                remNode.removeFromParent();
+        }
+    }
+    
+    public void treeNodesChanged(javax.swing.event.TreeModelEvent treeModelEvent) {
+        debug("node changed");
+        TreeCellEditor editor = tree.getCellEditor();
+        Object newName = editor.getCellEditorValue();
+        
+        if((newName instanceof String) && selectedItem != null){
+            debug("new name");
+            //data of old item
+            Map.ID itemID = (Map.ID)dataMap.get(selectedItem);
+            //remove old data from dataMap
+            dataMap.remove(selectedItem);
+            FavoritesNode fromRootNode = (FavoritesNode)connections.get(getSelectedNode());
+            //change name of old Item
+            selectedItem.setName((String)newName);
+            selectedNode.setUserObject(selectedItem);       
+            if(fromRootNode != null){
+                FavoritesItem fromRootItem = (FavoritesItem) fromRootNode.getUserObject();
+                fromRootItem.setName((String)newName);
+            }
+            //put data to the dataMap
+            dataMap.put(selectedItem,itemID);
+            saveFavorites();
+        }
+    }
+    
+    /**
+     * Returns the selected node
+     *
+     */
+    public FavoritesNode getSelectedNode() {
+        return selectedNode;
+    }
+    
+    /**
+     * AddAction class.
+     *
+     */
+    public class AddAction extends AbstractAction{
+        
+        public AddAction(){
+            super(HelpUtilities.getString(locale, "favorites.add"), SwingHelpUtilities.getImageIcon(BasicFavoritesNavigatorUI.class,"images/addToFav.gif"));
+        }
+        
+        public void actionPerformed(ActionEvent ev){
+            debug("add");
+
+            String target = null;
+            String hstitle = null;
+            FavoritesItem favorite = null;
+	    HelpModel helpModel = favorites.getModel();
+	    HelpSet hs = helpModel.getHelpSet();
+
+            Map.ID ID = helpModel.getCurrentID();
+            URL url = helpModel.getCurrentURL();
+            if(ID != null){
+                target = ID.id;
+                hstitle = ID.hs.getTitle();
+            }
+            if(hstitle == null){
+		// need to determine the helpset title by looking at the
+		// starting URL of the 
+		hstitle = getHelpSetTitle(hs, url);
+		if (hstitle == null) {
+		    hstitle=  hs.getTitle();
+		}
+            }
+            String urlSpec = null;
+            if(target == null) {
+                urlSpec = url.toExternalForm();
+	    }
+            favorite = new FavoritesItem(contentTitle, target, urlSpec,
+					 hstitle, Locale.getDefault());
+            dataMap.put(favorite,ID);
+ 
+            FavoritesNode node = new FavoritesNode(favorite);
+            DefaultTreeModel model = (DefaultTreeModel)tree.getModel();
+            model.insertNodeInto(node, topNode, topNode.getChildCount());
+            
+            TreePath path = new TreePath(node.getPath());
+            tree.expandPath(path);
+            tree.setSelectionPath(path);
+            tree.scrollPathToVisible(path);
+
+            saveFavorites();
+        }
+
+	/**
+	 * retuns a helpset title for a given url
+	 */
+	private String getHelpSetTitle(HelpSet hs, URL url) {
+	    URL baseURL = hs.getHelpSetURL();
+	    String urlExternal = url.toExternalForm();
+	    String baseURLExternal = baseURL.toExternalForm();
+	    if (urlExternal.startsWith(baseURLExternal)) {
+		return hs.getTitle();
+	    }
+	    Enumeration helpsets = hs.getHelpSets();
+	    String title = null;
+	    while (helpsets.hasMoreElements()) {
+		HelpSet testHS = (HelpSet) helpsets.nextElement();
+		title = getHelpSetTitle(testHS, url);
+		if (title != null) {
+		    break;
+		}
+	    }
+	    return title;
+	}
+
+    }
+    
+    /**
+     * Returns the Add action
+     *
+     */
+    public Action getAddAction(){
+        return addAction;
+    }
+    
+    /**
+     * RemoveAction class.
+     *
+     */
+    public class RemoveAction extends AbstractAction{
+        
+        public RemoveAction(){
+            super(HelpUtilities.getString(locale, "favorites.remove"), SwingHelpUtilities.getImageIcon(BasicFavoritesNavigatorUI.class,"images/remove.gif"));
+        }
+        
+        public void actionPerformed(ActionEvent ev){
+            debug("remove");
+            DefaultMutableTreeNode node = null;
+            DefaultTreeModel model = (DefaultTreeModel)tree.getModel();
+            TreePath[] paths = tree.getSelectionPaths();
+            for(int i = 0 ; i < paths.length; i++){
+                if(paths[i] != null){
+                    node = (DefaultMutableTreeNode)paths[i].getLastPathComponent();
+                    model.removeNodeFromParent(node);
+                    if(node != null){
+                        FavoritesItem item = (FavoritesItem)node.getUserObject();
+                        dataMap.remove(item);
+                    }
+                }
+                saveFavorites();
+            }
+        }
+    }
+    
+    /**
+     * Returns the RemoveAction object
+     */
+    public Action getRemoveAction(){
+        return removeAction;
+    }
+    
+    /**
+     * FolderAction class.
+     *
+     */
+    public class FolderAction extends AbstractAction{
+        
+        public FolderAction(){
+            super(HelpUtilities.getString(locale, "favorites.folder"), SwingHelpUtilities.getImageIcon(BasicFavoritesNavigatorUI.class,"images/folder.gif"));
+        }
+        
+        public void actionPerformed(ActionEvent ev){
+            FavoritesItem favoriteFolder = new FavoritesItem(HelpUtilities.getString(locale, "favorites.folder"));
+            favoriteFolder.setAsFolder();
+            FavoritesNode node = new FavoritesNode(favoriteFolder);
+            TreePath nodePath = tree.getSelectionPath();
+            TreeNode parent = null;
+            if(nodePath == null)
+                parent = topNode;
+            else{
+                FavoritesNode selNode = (FavoritesNode)nodePath.getLastPathComponent();
+                parent = selNode.getParent();
+            }
+            DefaultTreeModel model = (DefaultTreeModel)tree.getModel();
+            model.insertNodeInto(node,(DefaultMutableTreeNode)parent,parent.getChildCount());
+            TreePath path = new TreePath(node.getPath());
+            tree.expandPath(path);
+            tree.setSelectionPath(path);
+            tree.scrollPathToVisible(path);
+            saveFavorites();
+        }
+    }
+    
+    /**
+     * Returns the FolderAction object
+     */
+    public Action getFolderAction(){
+        return folderAction;
+    }
+    
+    /**
+     * CutAction class.
+     */
+    public class CutAction extends AbstractAction{
+        
+        public CutAction(){
+            super(HelpUtilities.getString(locale,"favorites.cut"));
+        }
+        
+        public void actionPerformed(ActionEvent ev){
+            debug("cut");
+            DefaultMutableTreeNode node = null;
+            nodeClipboard.removeAllElements();
+            DefaultTreeModel model = (DefaultTreeModel)tree.getModel();
+            TreePath[] paths = tree.getSelectionPaths();
+            for(int i = 0 ; i < paths.length; i++){
+                if(paths[i] != null){
+                    node = (DefaultMutableTreeNode)paths[i].getLastPathComponent();
+                    if(node != null){
+                        FavoritesItem item = (FavoritesItem)node.getUserObject();
+                        nodeClipboard.add(node);
+                    }
+                    model.removeNodeFromParent(node);
+                }
+            }
+            saveFavorites();
+            pasteMI.setEnabled(true);
+        }
+    }
+    
+    /**
+     * Returns the CutAction object
+     */
+    public Action getCutAction(){
+        return cutAction;
+    }
+    
+    /**
+     * PasteAction class.
+     */
+    public class PasteAction extends AbstractAction{
+        
+        public PasteAction(){
+            super(HelpUtilities.getString(locale,"favorites.paste"));
+        }
+        
+        public void actionPerformed(ActionEvent ev){
+            debug("paste");
+            
+            DefaultTreeModel model = (DefaultTreeModel)tree.getModel();
+            TreePath path = tree.getSelectionPath();
+            FavoritesNode node = (FavoritesNode)path.getLastPathComponent();
+            if(node != null){
+                if(node.getAllowsChildren()){
+                    for(Enumeration nodes = nodeClipboard.elements(); nodes.hasMoreElements();){
+                        model.insertNodeInto((DefaultMutableTreeNode)nodes.nextElement(),(DefaultMutableTreeNode)node,node.getChildCount());
+                    }
+                }
+                else{
+                    DefaultMutableTreeNode parent = (DefaultMutableTreeNode)node.getParent();
+                    if(parent == null)
+                        return;
+                    int index = parent.getIndex(node);
+                    for(Enumeration en = nodeClipboard.elements(); en.hasMoreElements();index++){
+                        model.insertNodeInto((DefaultMutableTreeNode)en.nextElement(),parent,index);
+                    }
+                }
+                saveFavorites();
+            }
+            
+        }
+    }
+    
+    /**
+     * Returns the PasteAction object
+     */
+    public Action getPasteAction(){
+        return pasteAction;
+    }
+    
+    /**
+     * CopyAction class.
+     */
+    public class CopyAction extends AbstractAction{
+        
+        public CopyAction(){
+            super(HelpUtilities.getString(locale,"favorites.copy"));
+        }
+        
+        public void actionPerformed(ActionEvent ev){
+            debug("paste");
+            
+            DefaultMutableTreeNode node = null;
+            nodeClipboard.removeAllElements();
+            DefaultTreeModel model = (DefaultTreeModel)tree.getModel();
+            TreePath[] paths = tree.getSelectionPaths();
+            for(int i = 0 ; i < paths.length; i++){
+                if(paths[i] != null){
+                    node = (DefaultMutableTreeNode)paths[i].getLastPathComponent();
+                    if(node != null){
+                        FavoritesItem item = (FavoritesItem)node.getUserObject();
+                        FavoritesNode copy = ((FavoritesNode)node).getDeepCopy();
+                        nodeClipboard.add(copy);
+                    }
+                }
+            }
+            saveFavorites();
+            pasteMI.setEnabled(true);
+        }
+    }
+    
+    /**
+     * Returns the CopyAction Object
+     */
+    public Action getCopyAction(){
+        return copyAction;
+    }
+    
+    /**
+     * PopupListener class
+     */
+    public class PopupListener extends MouseAdapter{
+        
+        public void mousePressed(MouseEvent e){
+	    maybeShowPopup(e);
+        }
+
+        public void mouseReleased(MouseEvent e){
+	    maybeShowPopup(e);
+        }
+
+	private void maybeShowPopup(MouseEvent e) {
+            TreePath path = tree.getSelectionPath();
+            TreePath clickPath = tree.getPathForLocation(e.getX(),e.getY());
+            if (e.isPopupTrigger()) { 
+		if (path != null && path.equals(clickPath)) {
+		    separatorMI.setVisible(true);
+		    cutMI.setVisible(true);
+		    copyMI.setVisible(true);
+		    pasteMI.setVisible(true);
+		    removeMI.setVisible(true);
+		} else {
+		    separatorMI.setVisible(false);
+		    cutMI.setVisible(false);
+		    copyMI.setVisible(false);
+		    pasteMI.setVisible(false);
+		    removeMI.setVisible(false);
+		}
+                popup.show(e.getComponent(), e.getX(), e.getY());
+	    }
+	}
+    }
+    
+    /**
+     * Class for JTree supported D&D features.
+     */
+    public class FavoritesTree extends JTree implements DragGestureListener, DropTargetListener, DragSourceListener {
+        
+        protected Map.ID selectedID = null;
+        
+        private DragSource dragSource = null;
+        private DragSourceContext dragSourceContext = null;
+        private Point cursorLocation = null;
+        private TreePath pathSource;
+        private BufferedImage ghostImage;
+        private Point offset = new Point();
+        private Point ptLast = new Point();
+        private Rectangle2D ghostRect = new Rectangle2D.Float();
+        
+        /**
+         * Data object of selected FavoritesNode
+         */
+        private Map.ID hashCandidate;
+        /**
+         * Custom cursor
+         */
+        private Cursor dndCursor;
+        
+        /**
+         * Creates FavoritesTree
+         *
+         * @param root The root node of the tree
+         */
+        public FavoritesTree(FavoritesNode root) {
+            super(root);
+            
+            setEditable(true);
+            
+            dragSource = DragSource.getDefaultDragSource();
+            
+            DragGestureRecognizer dgr =
+            dragSource.createDefaultDragGestureRecognizer(this,DnDConstants.ACTION_COPY_OR_MOVE,this);
+            
+            dgr.setSourceActions((dgr.getSourceActions()) &~ (InputEvent.BUTTON3_MASK));
+            
+            DropTarget dropTarget = new DropTarget(this, this);
+            
+            Toolkit tk = this.getToolkit();
+            if(tk.getBestCursorSize(16,16).equals(new Dimension(64,64)))
+                dndCursor = (Cursor) UIManager.get("HelpDnDCursor");
+            if(dndCursor == null)
+                debug("cursor is null");
+            putClientProperty("JTree.lineStyle", "None");
+        }
+        
+        public void dragGestureRecognized(DragGestureEvent e) {
+            FavoritesNode dragNode = getSelectedNode();
+            if (dragNode != null) {
+                
+                ghostImage = createGhostImage(e);
+                Transferable transferable = (Transferable) dragNode.getUserObject();
+                hashCandidate = (Map.ID)dataMap.get((FavoritesItem)transferable);
+                
+                Cursor cursor = DragSource.DefaultCopyDrop;
+                int action = e.getDragAction();
+                if(action == DnDConstants.ACTION_MOVE){
+                    debug("action move");
+                    cursor = DragSource.DefaultMoveDrop;
+                }
+                
+                dragSource.startDrag(e,dndCursor,ghostImage,new Point(5,5), transferable,this);
+            }
+        }
+        
+        private BufferedImage createGhostImage(DragGestureEvent e){
+            debug("createGhostImage");
+            
+            BufferedImage ghostImage = null;
+            Point ptDragOrigin = e.getDragOrigin();
+            TreePath path = getPathForLocation(ptDragOrigin.x, ptDragOrigin.y);
+            if (path == null)
+                return ghostImage;
+            
+            Rectangle raPath = getPathBounds(path);
+            offset.setLocation(ptDragOrigin.x-raPath.x, ptDragOrigin.y-raPath.y);
+            
+            JLabel lbl = (JLabel) getCellRenderer().getTreeCellRendererComponent
+            (this,path.getLastPathComponent(),false, isExpanded(path),getModel().isLeaf(path.getLastPathComponent()),0,false);
+            lbl.setSize((int)raPath.getWidth(), (int)raPath.getHeight()); 
+            
+            ghostImage = new BufferedImage((int)raPath.getWidth(), (int)raPath.getHeight(), BufferedImage.TYPE_INT_ARGB_PRE);
+            Graphics2D g2 = ghostImage.createGraphics();
+            
+            g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC, 0.5f));
+            lbl.paint(g2);
+            
+            Icon icon = lbl.getIcon();
+            int nStartOfText = (icon == null) ? 0 : icon.getIconWidth()+lbl.getIconTextGap();
+            g2.setComposite(AlphaComposite.getInstance(AlphaComposite.DST_OVER, 0.5f));
+            g2.setPaint(new GradientPaint(nStartOfText,	0, SystemColor.controlShadow,
+            getWidth(),	0, new Color(255,255,255,0)));
+            g2.fillRect(nStartOfText, 0, getWidth(), ghostImage.getHeight());
+            
+            g2.dispose();
+            
+            return ghostImage;
+        }
+        
+        public void dragDropEnd(DragSourceDropEvent dsde) {
+            debug("dragDropEnd");
+        }
+        
+        public void dragEnter(DragSourceDragEvent dsde) {
+            debug("dragEnter");
+            setCursor(dsde);
+        }
+        
+        public void dragOver(DragSourceDragEvent dsde) {
+            debug("drag over");
+            setCursor(dsde);
+        }
+        
+        public void dropActionChanged(DragSourceDragEvent dsde) {
+            debug("dropActionChanged");
+            setCursor(dsde);
+        }
+        
+        public void dragExit(DragSourceEvent dsde) {
+            debug("dragExit");
+        }
+        
+        /**
+         * Sets appropriate cursor type according to event
+         *
+         * @param dsde DrageSourceDrageEvent
+         */
+        private void setCursor(DragSourceDragEvent dsde) {
+            
+            if (cursorLocation == null) return;
+            
+            TreePath destinationPath =
+            getPathForLocation(cursorLocation.x, cursorLocation.y);
+            
+            DragSourceContext dsc = dsde.getDragSourceContext();
+            
+            if (testDropTarget(destinationPath, selectedTreePath) == null){
+                dsc.setCursor(DragSource.DefaultCopyDrop);
+                
+            }
+            else {
+                dsc.setCursor(DragSource.DefaultCopyNoDrop);
+            }
+        }
+        
+        public void drop(DropTargetDropEvent e) {
+            debug("drop");
+            try {
+                Transferable tr = e.getTransferable();
+                
+                if (!tr.isDataFlavorSupported( FavoritesItem.FAVORITES_FLAVOR)){
+                    debug("drop rejected not data flavor");
+                    e.rejectDrop();
+                }
+                
+                FavoritesItem childInfo = (FavoritesItem) tr.getTransferData( FavoritesItem.FAVORITES_FLAVOR );
+                Point loc = e.getLocation();
+                TreePath destinationPath = getPathForLocation(loc.x, loc.y);
+                
+                final String msg = testDropTarget(destinationPath, selectedTreePath);
+                if (msg != null) {
+                    e.rejectDrop();
+                    debug("Error : "+msg);
+                    return;
+                }
+                
+                FavoritesNode newParent =
+                (FavoritesNode) destinationPath.getLastPathComponent();
+                
+                debug("new parent: "+newParent);
+                //get old parent node
+                FavoritesNode oldParent = (FavoritesNode) getSelectedNode().getParent();
+                
+                FavoritesNode selNode = (FavoritesNode) getSelectedNode();
+                FavoritesItem selItem = (FavoritesItem) selNode.getUserObject();
+                
+                FavoritesNode newNode = selNode.getDeepCopy();
+                
+                int action = e.getDropAction();
+                boolean copyAction = (action == DnDConstants.ACTION_COPY);
+                debug("copy action: "+ copyAction);
+                //make new child node
+                FavoritesNode newChild = new FavoritesNode(childInfo);
+                debug("new child: "+newChild);
+                try {
+                    if (!copyAction){
+                        FavoritesNode fromRootNode = (FavoritesNode)connections.get(getSelectedNode());
+                        if(fromRootNode != null)
+                            fromRootNode.removeFromParent();
+                        oldParent.remove(getSelectedNode());
+                    }
+                    DefaultTreeModel model = (DefaultTreeModel)getModel();
+                    
+                    if (!newParent.getAllowsChildren()){
+                        TreeNode parent = newParent.getParent();
+                        if(parent != null){
+                            int index = parent.getIndex(newParent);
+                            model.insertNodeInto(newNode,(DefaultMutableTreeNode)parent, index+1);
+                        }
+                    }else
+                        model.insertNodeInto(newNode,newParent,newParent.getChildCount());
+                    
+                    if (copyAction)
+                        e.acceptDrop(DnDConstants.ACTION_COPY);
+                    else e.acceptDrop(DnDConstants.ACTION_MOVE);
+                }
+                catch (java.lang.IllegalStateException ils) {
+                    debug("drop ejected");
+                    e.rejectDrop();
+                }
+                
+                e.getDropTargetContext().dropComplete(true);
+                
+                FavoritesItem newItem = (FavoritesItem) newNode.getUserObject();
+                dataMap.put(newItem, hashCandidate);
+                DefaultTreeModel model = (DefaultTreeModel) getModel();
+                model.reload(oldParent);
+                model.reload(newParent);
+                TreePath parentPath = new TreePath(newParent.getPath());
+                expandPath(parentPath);
+                saveFavorites();
+            }
+            catch (IOException io) {
+                e.rejectDrop();
+                debug("drop rejected" + io);
+            }
+            catch (UnsupportedFlavorException ufe) {
+                e.rejectDrop();
+                debug("drop rejected: "+ ufe);
+            }
+        }
+        
+        public void dragEnter(DropTargetDragEvent e) {
+        }
+        
+        public void dragExit(DropTargetEvent e) {
+            if (!DragSource.isDragImageSupported()) {
+                repaint(ghostRect.getBounds());
+            }
+        }
+        
+        public void dragOver(DropTargetDragEvent e) {
+            
+            Point pt = e.getLocation();
+            if (pt.equals(ptLast))
+                return;
+            
+            ptLast = pt;
+            
+            Point cursorLocationBis = e.getLocation();
+            TreePath destinationPath = getPathForLocation(cursorLocationBis.x, cursorLocationBis.y);
+            
+            Graphics2D g2 = (Graphics2D) getGraphics();
+            
+            if(testDropTarget(destinationPath, selectedTreePath) == null){
+                e.acceptDrag(DnDConstants.ACTION_COPY_OR_MOVE);
+                if (!DragSource.isDragImageSupported()) {
+                    paintImmediately(ghostRect.getBounds());
+                    ghostRect.setRect(pt.x - offset.x, pt.y - offset.y, ghostImage.getWidth(), ghostImage.getHeight());
+                    g2.drawImage(ghostImage, AffineTransform.getTranslateInstance(ghostRect.getX(), ghostRect.getY()), null);
+                }
+            }else
+                e.rejectDrag();
+        }
+        
+        public void dropActionChanged(DropTargetDragEvent e) {
+        }
+        
+        /**
+         * Tests whether drop location is valid or not
+         *
+         * @param destination The destination path
+         * @param dropper The path for the node to be dropped
+         * @return Null if no problems, otherwise an explanation
+         */
+        private String testDropTarget(TreePath destination, TreePath dropper) {
+            
+            boolean destinationPathIsNull = destination == null;
+            if (destinationPathIsNull){
+                return "Invalid drop location.";
+                //remove ghostLikeImage
+            }
+            
+            FavoritesNode node = (FavoritesNode) destination.getLastPathComponent();
+            
+            if (destination.equals(dropper))
+                return "Destination cannot be same as source";
+            
+            
+            if ( dropper.isDescendant(destination))
+                return "Destination node cannot be a descendant.";
+            
+            
+            if ( dropper.getParentPath().equals(destination))
+                return "Destination node cannot be a parent.";
+            
+            return null;
+        }
+    }
+    
+    /**
+     * For printf debugging.
+     */
+    private static boolean debug = false;
+    private static void debug(String str) {
+        if (debug) {
+            System.out.println("BasicFavoritesNavigatorUI: " + str);
+        }
+    }
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicGlossaryNavigatorUI.java b/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicGlossaryNavigatorUI.java
new file mode 100644
index 0000000000000000000000000000000000000000..bcb8bb689bc8218f73c4266c84601ba8a969198c
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicGlossaryNavigatorUI.java
@@ -0,0 +1,747 @@
+/*
+ * @(#)BasicGlossaryNavigatorUI.java	1.8 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help.plaf.basic;
+
+import javax.help.*;
+import javax.help.plaf.HelpNavigatorUI;
+import javax.help.plaf.HelpUI;
+import javax.help.plaf.basic.BasicHelpUI;
+import javax.help.plaf.basic.BasicIndexCellRenderer;
+import javax.help.event.HelpModelListener;
+import javax.help.event.HelpModelEvent;
+import java.util.EventObject;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+import javax.swing.*;
+import javax.swing.plaf.ComponentUI;
+import javax.swing.tree.*;
+import javax.swing.event.*;
+import java.awt.*;
+import java.awt.event.*;
+import java.io.Reader;
+import java.io.Serializable;
+import java.net.URL;
+import java.net.URLConnection;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import javax.help.Map.ID;
+import java.text.Collator;
+import java.text.RuleBasedCollator;
+import java.util.Locale;
+import java.util.Stack;
+
+/**
+ * The default UI for JHelpNavigator of type Glossary.
+ *
+ * @author Roger D. Brinkley
+ * @author Richard Gregor
+ * @version   1.8     10/30/06
+ */
+
+public class BasicGlossaryNavigatorUI extends HelpNavigatorUI
+implements HelpModelListener, TreeSelectionListener,
+PropertyChangeListener, ActionListener, Serializable {
+    protected JHelpGlossaryNavigator glossary;
+    protected JScrollPane sp;
+    protected DefaultMutableTreeNode topNode;
+    protected JTree tree;
+    protected JTextField searchField;
+    protected RuleBasedCollator rbc;
+    protected String oldText;
+    protected DefaultMutableTreeNode currentFindNode;
+    protected JHelpContentViewer viewer;
+    
+    /**
+     * Creates UI
+     */
+    public static ComponentUI createUI(JComponent x) {
+        return new BasicGlossaryNavigatorUI((JHelpGlossaryNavigator) x);
+    }
+    
+    public BasicGlossaryNavigatorUI(JHelpGlossaryNavigator b) {
+        ImageIcon icon = getImageIcon(b.getNavigatorView());
+        if (icon != null) {
+            setIcon(icon);
+        } else {
+	    setIcon(UIManager.getIcon("GlossaryNav.icon"));
+	}
+    }
+    
+    public void installUI(JComponent c) {
+        debug("installUI");
+        
+        glossary = (JHelpGlossaryNavigator)c;
+        HelpModel model = glossary.getModel();
+        
+        glossary.setLayout(new BorderLayout());
+        glossary.addPropertyChangeListener(this);
+        if (model != null) {
+            //model.addHelpModelListener(this); // for our own changes
+        }
+        
+        topNode = new DefaultMutableTreeNode();
+        
+        JLabel search = new JLabel(HelpUtilities.getString(HelpUtilities.getLocale(c),
+        "index.findLabel"));
+        searchField= new JTextField();
+        search.setLabelFor(searchField);
+        
+        searchField.addActionListener(this);
+        JPanel box = new JPanel();
+        box.setLayout(new BoxLayout(box, BoxLayout.X_AXIS));
+        box.add(search);
+        box.add(searchField);
+        
+        glossary.add("North", box);
+        
+        tree = new JTree(topNode);
+        TreeSelectionModel tsm = tree.getSelectionModel();
+        tsm.addTreeSelectionListener(this);
+        tree.setShowsRootHandles(true);
+        tree.setRootVisible(false);
+        
+        setCellRenderer(glossary.getNavigatorView(), tree);
+        
+        sp = new JScrollPane();
+        sp.getViewport().add(tree);
+        
+        JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, false);
+        splitPane.setOneTouchExpandable(true);
+        
+        splitPane.setTopComponent(sp);
+        
+        viewer = new JHelpContentViewer(model.getHelpSet());
+        viewer.setSynch(false);
+        splitPane.setBottomComponent(viewer);
+        
+        glossary.add("Center",splitPane);
+        splitPane.setDividerLocation(180);
+        
+        reloadData();
+    }
+    
+    /**
+     * Sets the desired cell renderer on this tree.
+     * This is exposed for redefinition
+     * by subclases.
+     */
+    protected void setCellRenderer(NavigatorView view, JTree tree) {
+        tree.setCellRenderer(new BasicIndexCellRenderer());
+    }
+    
+    /**
+     * Uninstalls UI
+     */
+    public void uninstallUI(JComponent c) {
+        debug("uninstallUI");
+        HelpModel model = glossary.getModel();
+        
+        glossary.removePropertyChangeListener(this);
+        TreeSelectionModel tsm = tree.getSelectionModel();
+        tsm.removeTreeSelectionListener(this);
+        glossary.setLayout(null);
+        glossary.removeAll();
+        
+        if (model != null) {
+            model.removeHelpModelListener(this);
+        }
+        
+        glossary = null;
+    }
+    
+ 
+    public Dimension getPreferredSize(JComponent c) {
+        
+        return new Dimension(200,100);
+        
+    }
+    
+    public Dimension getMinimumSize(JComponent c) {
+        return new Dimension(100,100);
+    }
+ 
+    public Dimension getMaximumSize(JComponent c) {
+        return new Dimension(Short.MAX_VALUE, Short.MAX_VALUE);
+    }
+    
+    private void reloadData() {
+        debug("reloadData");
+                
+        // parse the glossary data into topNode
+        GlossaryView view = (GlossaryView) glossary.getNavigatorView();
+	loadData(view);
+    }
+
+    private void loadData(GlossaryView view) {
+
+       if (view == null) {
+            return;
+        }
+        
+        // remove all children
+        topNode.removeAllChildren();
+        
+        String mergeType = view.getMergeType();
+        
+        Locale locale = view.getHelpSet().getLocale();
+        
+        DefaultMutableTreeNode node = view.getDataAsTree();
+        
+	// Make sure the children are all handled correctly
+	MergeHelpUtilities.mergeNodeChildren(mergeType, node);
+        
+        // This is a tricky one. As you remove the entries from one node to
+        // another the list shrinks. So you can't use an Enumated list to do
+        // the move.
+        while (node.getChildCount() > 0) {
+            topNode.add((DefaultMutableTreeNode) node.getFirstChild());
+        }
+        
+        // add all subhelpsets
+        addSubHelpSets(view.getHelpSet());        
+
+        // reload the tree data
+        ((DefaultTreeModel)tree.getModel()).reload();
+        
+        setVisibility(topNode);
+    }
+    
+    /**
+     * Reloads the presentation data using new help model. Changes the navigator if new model contains
+     * view with the same name as former view
+     **/
+    private void reloadData(HelpModel model) {
+        debug("reloadData in using new model");
+        GlossaryView glossaryView = null;
+        
+        HelpSet newHelpSet = model.getHelpSet();
+        GlossaryView oldView = (GlossaryView) glossary.getNavigatorView();
+        String oldName = oldView.getName();
+        NavigatorView[] navViews = newHelpSet.getNavigatorViews();
+        for(int i = 0 ; i < navViews.length; i++){
+            if((navViews[i].getName()).equals(oldName)){
+                NavigatorView tempView = navViews[i];
+                if(tempView instanceof GlossaryView){
+                    glossaryView = (GlossaryView) tempView;
+                    break;
+                }
+            }
+        }
+ 
+	loadData(glossaryView);
+    }
+
+    /** Adds subhelpsets
+     *
+     * @param hs The HelpSet which subhelpsets will be added
+     */
+    protected void addSubHelpSets(HelpSet hs){
+	debug ("addSubHelpSets");
+        for( Enumeration e = hs.getHelpSets(); e.hasMoreElements(); ) {
+            HelpSet ehs = (HelpSet) e.nextElement();
+            // merge views
+            NavigatorView[] views = ehs.getNavigatorViews();
+            for(int i = 0; i < views.length; i++){
+                if(glossary.canMerge(views[i]))
+                    merge(views[i]);
+            }
+            addSubHelpSets( ehs );
+        }
+    }
+
+    /**
+     * Expands entry path and entry itself( when entry is not empty) for specific id
+     *
+     * @param target The target of entry
+     */
+    
+    private void expand(String target){
+        debug("expand called");
+        //find all nodes with certain id
+        Enumeration nodes = findNodes(target).elements();
+        DefaultMutableTreeNode node = null;
+        
+        while(nodes.hasMoreElements()){
+            node = (DefaultMutableTreeNode)nodes.nextElement();
+            debug("expandPath :"+node);
+            if(node.getChildCount() > 0){
+                DefaultMutableTreeNode child =(DefaultMutableTreeNode) node.getFirstChild();
+                TreePath path = new TreePath(child.getPath());
+                tree.makeVisible(path);
+            }
+            else{
+                TreeNode[] treeNode = node.getPath();
+                TreePath path = new TreePath(treeNode);
+                //tree.scrollPathToVisible(path);
+                tree.makeVisible(path);
+            }
+        }
+    }    
+    
+    /**
+     * Returns all nodes with certain id
+     *
+     * @param target The target of entry
+     *
+     */
+    private Vector findNodes(String target){
+        Enumeration nodes = topNode.preorderEnumeration();
+        DefaultMutableTreeNode node = null;
+        Vector nodeFound = new Vector();
+        
+        while(nodes.hasMoreElements()){
+            node = (DefaultMutableTreeNode)nodes.nextElement();
+            debug(" node :"+ node.toString());
+            if(node != null){
+                IndexItem indexItem = (IndexItem)node.getUserObject();
+                if(indexItem == null)
+                    debug("indexItem is null");
+                else{
+                    Map.ID id = indexItem.getID();
+                    if(id != null){
+                        debug("id name :"+id.id);
+                        debug("target :"+target);
+                        Map.ID itemID = null;
+                        try{
+                            itemID = Map.ID.create(target,glossary.getModel().getHelpSet());
+                        }
+                        catch(BadIDException exp){
+                            System.err.println("Not valid ID :"+target );
+                            break;
+                        }
+                        if(id.equals(itemID))
+                            nodeFound.addElement(node);
+                    }
+                }
+            }
+        }
+        
+        return nodeFound;
+    }
+    
+    /**
+     * Collapses entry specified by id. If entry is empty collapses it's parent.
+     *
+     * @param target The target of entry
+     */
+    
+    private void collapse(String target){
+        Enumeration nodes = findNodes(target).elements();
+        DefaultMutableTreeNode node = null;
+        debug("collapse called");
+        
+        while(nodes.hasMoreElements()){
+            node = (DefaultMutableTreeNode)nodes.nextElement();
+            if(node.getChildCount() > 0){
+                TreeNode[] treeNode = node.getPath();
+                TreePath path = new TreePath(treeNode);
+                tree.collapsePath(path);
+                tree.collapseRow(tree.getRowForPath(path));
+            }
+            else{
+                DefaultMutableTreeNode parent =(DefaultMutableTreeNode) node.getParent();
+                TreePath path = new TreePath(parent.getPath());
+                tree.collapseRow(tree.getRowForPath(path));
+            }
+        }
+    }
+    
+    
+    /**
+     * Merges in the navigational data from another IndexView.
+     */
+
+    public void doMerge(NavigatorView view) {
+	debug("merging data");
+       
+        Merge mergeObject = Merge.DefaultMergeFactory.getMerge(glossary.getNavigatorView(),view);
+        if(mergeObject != null) {
+            mergeObject.processMerge(topNode);
+	}
+        
+    }
+
+    /**
+     * Merges in the navigational data from another TOCView.
+     *
+     * @param view A GlossaryView.  Note the actual argument is a NavigatorView type
+     * so it replaces the correct NavigatorUI method.
+     */
+    
+    public void merge(NavigatorView view) {
+        debug("merging data");
+	doMerge(view);
+
+        //reload the tree data
+	((DefaultTreeModel)tree.getModel()).reload(); 
+	setVisibility(topNode);
+    }
+
+    /**
+     * Removes the navigational data from another GlossaryView.
+     *
+     * @param view An GlossaryView.  Note the actual argument is a NavigatorView type
+     * so it replaces the correct NavigatorUI method.
+     */
+    
+    public void remove(NavigatorView view) {
+        debug("removing "+view);
+        
+	remove(topNode, view.getHelpSet());
+        
+        // reload the tree data
+        ((DefaultTreeModel)tree.getModel()).reload();
+        setVisibility(topNode);
+    }
+    
+    /**
+     * Recursively removes all children of the node that have either hs or a HelpSet that
+     * is included in hs as their HelpSet data.
+     *
+     * Recursion is stopped when a node is removed.  This is because of the
+     * property of the merge mechanism.
+     *
+     * @param node The node from which to remove children.
+     * @param hs The non-null HelpSet to use.
+     */
+    
+    private void remove(DefaultMutableTreeNode node,
+			HelpSet hs) {
+	debug("remove("+node+", "+hs+")");
+
+	// a simple node.children() does not work because the
+	// enumeration is voided when a child is removed
+
+	// getNextSibling() has a linear search, so we won't do that either
+
+	// Collect all to be removed
+	Vector toRemove = new Vector();
+	
+	for (Enumeration e = node.children();
+	     e.hasMoreElements(); ) {
+	    DefaultMutableTreeNode child
+		= (DefaultMutableTreeNode) e.nextElement();
+	    debug("  considering "+child);
+	    IndexItem item = (IndexItem) child.getUserObject();
+	    HelpSet chs = item.getHelpSet();
+	    debug ("chs=" + chs + " hs.contains(chs)=" + hs.contains(chs));
+	    if (chs != null &&
+		hs.contains(chs)) {
+		if (child.isLeaf()) {
+		    // if the child has no children then just remove it
+		    debug("  tagging for removal: "+child);
+		    toRemove.addElement(child); // tag to be removed...
+		} else {
+		    // be carefull here. While the child hs is one to be
+		    // removed it is possible that there are children that
+		    // are not of this hs. Attempt to remove the 
+		    // child's children first. If they're are any children left
+		    // the change the hs to be the hs of the first child
+		    remove(child, hs);
+		    if (child.isLeaf()) {
+			// no more children remove the child as well
+			debug("  tagging for removal: "+child);
+			toRemove.addElement(child); // tag to be removed...
+		    } else {
+			// nuts! There are children from different hs
+			// change the hs of the IndexItem to be the hs of the
+			// first child
+			DefaultMutableTreeNode childOne = 
+			    (DefaultMutableTreeNode) child.getFirstChild();
+			IndexItem itemOne =  (IndexItem) childOne.getUserObject();
+			item.setHelpSet(itemOne.getHelpSet());
+			debug("  orphaned children - changing hs: "+child);
+		    }
+		}
+	    } else {
+		// the child doesn't need to be removed but possibly it's
+		// children will
+		remove(child, hs);
+	    }
+	}
+	    
+	// Now remove them
+	for (int i=0; i<toRemove.size(); i++) {
+	    debug("  removing "+toRemove.elementAt(i));
+	    node.remove((DefaultMutableTreeNode) toRemove.elementAt(i));
+	}
+    }
+
+    // Make all nodes visible
+    
+    private void setVisibility (DefaultMutableTreeNode node) {
+	IndexItem item = (IndexItem)node.getUserObject();
+	if (node == topNode || 
+	    (item != null && item.getExpansionType() != TreeItem.COLLAPSE)) {
+	    tree.expandPath(new TreePath(node.getPath()));
+	    if (! node.isLeaf()) {
+		int max = node.getChildCount();
+		for (int i=0; i<max; i++) {
+		    setVisibility((DefaultMutableTreeNode)node.getChildAt(i));
+		}
+	    }
+	}
+    }
+
+    // Process and idChanged event
+    
+    public void idChanged(HelpModelEvent e) {
+        ID id = e.getID();
+        HelpModel helpModel = glossary.getModel();
+        debug("idChanged("+e+")");
+        
+        if (e.getSource() != helpModel) {
+            System.err.println("Internal inconsistency!");
+            System.err.println("  "+e.getSource()+" != "+helpModel);
+            throw new Error("Internal error");
+        }
+        
+        if (id == null) {
+            //return;
+        }
+        TreePath s = tree.getSelectionPath();
+        if (s != null) {
+            Object o = s.getLastPathComponent();
+            // should require only a TreeNode
+            if (o instanceof DefaultMutableTreeNode) {
+                DefaultMutableTreeNode tn = (DefaultMutableTreeNode) o;
+                IndexItem item = (IndexItem) tn.getUserObject();
+                if (item != null) {
+                    ID nId = item.getID();
+                    if (nId != null && nId.equals(id)) {
+                        return;
+                    }
+                }
+            }
+        }
+        
+        DefaultMutableTreeNode node = findID(topNode, id);
+ 	selectNode(node);
+    }
+
+    // Note - this recursive implementation may need tuning for very large Index - epll
+
+    private DefaultMutableTreeNode findID(DefaultMutableTreeNode node, ID id) {
+        debug("findID: ("+id+")");
+        debug("  node: "+node);
+        
+        // check on the id
+        if (id == null) {
+            return null;
+        }
+        IndexItem item = (IndexItem) node.getUserObject();
+        if (item != null) {
+            ID testID = item.getID();
+            debug("  testID: "+testID);
+            if (testID != null && testID.equals(id)) {
+                return node;
+            }
+        }
+        int size = node.getChildCount();
+        for (int i=0; i<size ; i++) {
+            DefaultMutableTreeNode tmp =
+            (DefaultMutableTreeNode) node.getChildAt(i);
+            DefaultMutableTreeNode test = findID(tmp, id);
+            if (test != null) {
+                return test;
+            }
+        }
+        return null;
+    }
+
+    protected JHelpContentViewer getContentViewer() {
+        return viewer;
+    }
+
+    /**
+     * Select a certian node
+     */
+    private void selectNode(DefaultMutableTreeNode node) {
+	if (node == null) {
+	    // node doesn't exist. Need to clear the selection.
+	    tree.clearSelection();
+	    return;
+	}
+	TreePath path = new TreePath(node.getPath());
+	tree.expandPath(path);
+	tree.setSelectionPath(path);
+	tree.scrollPathToVisible(path);
+    }
+
+    protected JHelpNavigator getHelpNavigator() {
+        return glossary;
+    }
+
+    public void valueChanged(TreeSelectionEvent e) {
+
+        JHelpNavigator navigator = getHelpNavigator();
+        HelpModel helpmodel = navigator.getModel();
+
+        debug("ValueChanged: "+e);
+	debug("  model: "+helpmodel);
+
+        // send selected items into navigator
+        TreeItem[] items = null;
+        TreePath[] paths = tree.getSelectionPaths();
+        if (paths != null) {
+            items = new TreeItem[paths.length];
+            for (int i = 0; i < paths.length; i++) {
+                if (paths[i] != null) {
+                    DefaultMutableTreeNode node = (DefaultMutableTreeNode) paths[i].getLastPathComponent();
+                    items[i] = (TreeItem) node.getUserObject();
+                }
+            }
+        }
+        navigator.setSelectedItems(items);
+
+        // change current id only if one items is selected
+        if (items != null && items.length == 1) {
+            IndexItem item = (IndexItem) items[0];
+            if (item != null && item.getID() != null) {
+                try {
+                    getContentViewer().getModel().setCurrentID(item.getID(), item.getName(), navigator);
+                } catch (InvalidHelpSetContextException ex) {
+                    System.err.println("BadID: "+item.getID());
+                    return;
+                }
+            }
+        }
+    }
+
+    public void propertyChange(PropertyChangeEvent event) {
+        debug("propertyChange: " + event.getSource() + " "  +
+        event.getPropertyName());
+        
+        if (event.getSource() == glossary) {
+            String changeName = event.getPropertyName();
+            if (changeName.equals("helpModel")) {
+                debug("model changed");
+                reloadData((HelpModel)event.getNewValue());
+            } else  if (changeName.equals("font")) {
+                debug("Font change");
+                Font newFont = (Font)event.getNewValue();
+                tree.setFont(newFont);
+                RepaintManager.currentManager(tree).markCompletelyDirty(tree);
+            }else if(changeName.equals("expand")){
+                debug("Expand change");
+                expand((String)event.getNewValue());
+            } else if(changeName.equals("collapse")){
+                debug("Collapse change");
+                collapse((String)event.getNewValue());
+            }
+            // changes to UI property?
+        }
+    }
+    
+    /**
+     *  Handles Action from the JTextField component for searching.
+     */
+    public void actionPerformed(ActionEvent evt) {
+        if (evt.getSource()==searchField) {
+            
+            // get a Collator based on the component locale
+            rbc = (RuleBasedCollator) Collator.getInstance(glossary.getLocale());
+            
+            String text = searchField.getText();
+            if (text != null) {
+                text = text.toLowerCase();
+            }
+            if (oldText != null && text.compareTo(oldText) != 0) {
+                currentFindNode = null;
+            }
+            oldText = text;
+            
+            // find the node in the tree
+            DefaultMutableTreeNode node = searchName(topNode, text);
+            if (node == null) {
+                currentFindNode = null;
+                glossary.getToolkit().beep();
+                return;
+            }
+            currentFindNode = node;
+            
+            //display it
+            TreePath path = new TreePath(node.getPath());
+            tree.scrollPathToVisible(path);
+            tree.expandPath(path);
+            tree.setSelectionPath(path);
+            
+        }
+    }
+    
+    /**
+     *  Searches in the tree for an index item with a name that starts with String name.
+     *  Returns the node that contains the name,
+     *  returns null if no node is found.
+     */
+    private DefaultMutableTreeNode searchName(DefaultMutableTreeNode node,
+    String name) {
+        if (currentFindNode == null) {
+            IndexItem item = (IndexItem) node.getUserObject();
+            if (item!=null) {
+                String itemName = item.getName();
+                if (itemName !=null) {
+                    itemName = itemName.toLowerCase();
+                    // compare the Node with the Name
+                    //if (HelpUtilities.isStringInString(rbc, name, itemName)) {
+                    if(itemName.startsWith(name)){
+                        return node;
+                    }
+                }
+            }
+        } else {
+            if (currentFindNode == node) {
+                currentFindNode = null;
+            }
+        }
+        
+        // travel the the rest of the tree
+        int size = node.getChildCount();
+        for (int i=0; i<size ; i++) {
+            DefaultMutableTreeNode tmp =
+            (DefaultMutableTreeNode) node.getChildAt(i);
+            DefaultMutableTreeNode test = searchName(tmp, name);
+            if (test != null) {
+                return test;
+            }
+        }
+        return null;
+    }
+    
+    /**
+     * For printf debugging.
+     */
+    private static boolean debug = false;
+    private static void debug(String str) {
+        if (debug) {
+            System.out.println("BasicGlossaryNavigatorUI: " + str);
+        }
+    }
+    
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicHelpUI.java b/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicHelpUI.java
new file mode 100644
index 0000000000000000000000000000000000000000..3ed5628b5a5bdc615549e5d9b5599c4f2458bd0e
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicHelpUI.java
@@ -0,0 +1,513 @@
+/*
+ * @(#)BasicHelpUI.java	1.87 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+/*
+ * @(#) BasicHelpUI.java 1.87 - last change made 10/30/06
+ */
+
+package javax.help.plaf.basic;
+
+import javax.help.*;
+import javax.help.Map.ID;
+import javax.help.plaf.HelpUI;
+import javax.help.event.*;
+import java.util.Vector;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.Stack;
+import javax.swing.*;
+import javax.swing.text.*;
+import javax.swing.plaf.ComponentUI;
+import javax.swing.border.*;
+import javax.swing.event.*;
+import java.awt.*;
+import java.awt.event.*;
+import java.net.URL;
+import java.net.URLConnection;
+import java.net.MalformedURLException;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.io.*;
+import com.sun.java.help.impl.JHelpPrintHandler;
+import java.awt.datatransfer.DataFlavor;
+import java.lang.reflect.Method;
+import java.lang.reflect.Constructor;
+import javax.swing.Timer;
+
+/**
+ * The default UI for JHelp.
+ *
+ * @author Roger D. Brinkley
+ * @author Eduardo Pelegri-Llopart
+ * @author Stepan Marek
+ * @author Richard Gregor
+ * @version   1.87     10/30/06
+ */
+
+public class BasicHelpUI extends HelpUI implements PropertyChangeListener, Serializable {
+    protected JHelp help;
+    protected JToolBar toolbar;
+    protected JSplitPane splitPane;
+    protected JTabbedPane tabbedPane;
+    protected Vector navs=new Vector();
+    
+    private static Dimension PREF_SIZE = new Dimension(600,600);
+    private static Dimension MIN_SIZE = new Dimension(300,200);
+    static boolean noPageSetup = false;
+    
+    // Simple test to determine if pageSetup works on this system
+    // Yes for 1.2 on Windows, no for Solaris,Linux,HP
+    // Yes for 1.3
+    static {
+        boolean on1dot2 = false;
+        try {
+            // Test if method introduced in 1.3 is available.
+            Method m = DataFlavor.class.getMethod("getTextPlainUnicodeFlavor",
+						  (java.lang.Class[]) null);
+            on1dot2 = (m == null);
+        } catch (NoSuchMethodException e) {
+            on1dot2 = true;
+        }
+            
+        if (on1dot2) {
+            String osName[] = new String[] {""};
+            osName[0] = System.getProperty("os.name");
+            if (osName[0] != null) {
+                if ((osName[0].indexOf("Solaris") != -1) ||
+                (osName[0].indexOf("SunOS") != -1) ||
+                (osName[0].indexOf("Linux") != -1) ||
+                (osName[0].indexOf("HP-UX") != -1)) {
+                        noPageSetup = true;
+                }
+            }
+        }
+    }
+    
+    private int dividerLocation = 0;
+    private final double dividerLocationRatio = 0.30;
+    private JHelpFavoritesNavigator favorites = null;
+    
+    public static ComponentUI createUI(JComponent x) {
+        return new BasicHelpUI((JHelp) x);
+    }
+    
+    public BasicHelpUI(JHelp b) {
+        debug("createUI - sort of");
+    }
+    
+    public void installUI(JComponent c) {
+        debug("installUI");
+        help = (JHelp)c;
+        help.setLayout(new BorderLayout());
+        
+        // listen to property changes
+        help.addPropertyChangeListener(this);
+
+        // The navigators
+        tabbedPane = new JTabbedPane();
+        tabbedPane.setVisible(false);
+        
+        splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
+				   false,
+				   tabbedPane,
+				   help.getContentViewer());
+        
+        splitPane.setOneTouchExpandable(true);
+        help.add("Center", splitPane);
+        
+        JHelpNavigator first = null;
+        for (Enumeration e = help.getHelpNavigators(); e.hasMoreElements();) {
+            JHelpNavigator nav = (JHelpNavigator)e.nextElement();
+            if(nav instanceof JHelpFavoritesNavigator) {
+                favorites = (JHelpFavoritesNavigator)nav;
+	    }
+            addNavigator(nav);
+            if (first == null) {
+		first = nav;
+	    }
+        }
+        
+        debug("setting the current Navigator");
+        if (first != null) {
+            this.setCurrentNavigator(first);
+        }
+        // ToolBar should be visible externally.
+        
+        toolbar = createToolBar(HelpUtilities.getLocale(c));
+        if (toolbar != null) {
+            toolbar.setFloatable(false);
+            help.add("North", toolbar);
+        }
+        
+        // load everything
+        rebuild();
+    }
+    
+    protected JToolBar createToolBar(Locale locale) {
+        toolbar = new JToolBar();
+	Enumeration actions = null;
+	
+	// get the actions from the Presentation Toolbar if one exits
+ 	HelpSet.Presentation hsPres = help.getHelpSetPresentation();
+	if (hsPres != null && hsPres.isToolbar()) {
+	    actions = hsPres.getHelpActions(getModel().getHelpSet(), help);
+	} 
+	
+	if (actions == null || !actions.hasMoreElements()) {
+            actions = createDefaultActions();
+        }
+        
+	while (actions.hasMoreElements()) {
+            HelpAction action = (HelpAction)actions.nextElement();
+            if (action instanceof SeparatorAction) {
+                toolbar.addSeparator();
+            } else {
+                toolbar.add(new HelpButton(action));
+            }
+        }
+        
+        return toolbar;
+    }
+    
+    private Enumeration createDefaultActions() {
+        Vector actions = new Vector(5);
+        actions.add(new BackAction(help));
+        actions.add(new ForwardAction(help));
+        actions.add(new SeparatorAction(help));
+        actions.add(new PrintAction(help));
+        actions.add(new PrintSetupAction(help));
+	actions.add(new SeparatorAction(help));
+	if (favorites != null) {
+	    actions.add(new FavoritesAction(help));
+	}
+        return actions.elements();
+    }
+    
+    private class HelpButton extends JButton implements PropertyChangeListener {
+
+        HelpButton(HelpAction action) {
+            super();
+            
+            setEnabled(action.isEnabled());
+            
+            String name = (String)action.getValue("name");
+            
+            Icon icon = (Icon)action.getValue("icon");
+            if (icon == null) {
+                icon = UIManager.getIcon("HelpAction.icon");
+            }
+            setIcon(icon);
+
+	    Locale locale = null;
+	    try {
+		locale = help.getModel().getHelpSet().getLocale();
+	    } catch (NullPointerException npe) {
+		locale = Locale.getDefault();
+	    }
+            
+            String tooltip = (String)action.getValue("tooltip");
+            setToolTipText(tooltip);
+
+            String access = (String)action.getValue("access");
+            getAccessibleContext().setAccessibleName(access);
+            
+            if (action instanceof MouseListener) {
+                addMouseListener((MouseListener)action);
+            }
+            
+            if (action instanceof ActionListener) {
+                addActionListener((ActionListener)action);
+            }
+            
+            action.addPropertyChangeListener(this);
+            
+        }
+        
+        /**
+         * This method gets called when a bound property is changed.
+         * @param evt A PropertyChangeEvent object describing the event source
+         *  	and the property that has changed.
+         */
+        public void propertyChange(PropertyChangeEvent evt) {
+            if (evt.getPropertyName().equals("enabled")) {
+                setEnabled(((Boolean)evt.getNewValue()).booleanValue());
+            }
+        }
+            
+        private boolean createEnablePropertyChangeSupport(HelpAction action) {
+            boolean back = false;
+            try {
+                Class types[] = { String.class, PropertyChangeListener.class };
+                Method m = action.getClass().getMethod("addPropertyChangeListener", types);
+                Object args[] = { "enabled",  this };
+                m.invoke(action, args);
+                back = true;
+            } catch (Exception ex) {
+            }
+            return back;
+        }
+
+        private boolean createPropertyChangeSupport(HelpAction action) {
+            boolean back = false;
+            try {
+                Class types[] = { PropertyChangeListener.class };
+                Method m = action.getClass().getMethod("addPropertyChangeListener", types);
+                Object args[] = { this };
+                m.invoke(action, args);
+                back = true;
+            } catch (Exception ex) {
+            }
+            return back;
+        }
+
+    }
+
+    public void uninstallUI(JComponent c) {
+        debug("uninstallUI");
+        
+        help.removePropertyChangeListener(this);
+        help.setLayout(null);
+        help.removeAll();
+        
+        HelpModel hm = getModel();
+        if (hm != null) {
+           // hm.removeHelpModelListener(changeListener);
+        }
+
+        help = null;
+        toolbar = null;
+    }
+    
+    public Dimension getPreferredSize(JComponent c) {
+        return PREF_SIZE;
+    }
+    
+    public Dimension getMinimumSize(JComponent c) {
+        return MIN_SIZE;
+    }
+    
+    public Dimension getMaximumSize(JComponent c) {
+        // This doesn't seem right. But I'm not sure what to do for now
+        return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
+    }
+    
+    private void rebuild() {
+        HelpModel hm = getModel();
+        
+        if (hm == null) {
+            return;
+        }
+        //hm.addHelpModelListener(changeListener);
+        
+        // Discard any history
+        HelpHistoryModel historyModel = getHistoryModel();
+        if(historyModel != null)
+            historyModel.discard();
+        
+        try {
+	    Map.ID currentID = hm.getCurrentID();
+	    if (currentID == null) {
+		HelpSet hs = hm.getHelpSet();
+		Map.ID homeID = hs.getHomeID();
+		Locale locale = hs.getLocale();
+		String string = HelpUtilities.getString(locale, "history.homePage");
+		hm.setCurrentID(homeID, string, null);
+	    }
+        } catch (Exception e) {
+            // For example, a null HelpSet!
+            return;
+        }
+    }
+    
+    public void propertyChange(PropertyChangeEvent event) {
+        Object source = event.getSource();
+        String propertyName = event.getPropertyName();
+
+        debug("propertyChange: " + propertyName);
+
+        if (source == help) {
+            if (propertyName.equals("helpModel")) {
+                rebuild();
+            } else if (propertyName.equals("font")) {
+                debug("Font change");
+                Font newFont = (Font)event.getNewValue();
+                help.getContentViewer().setFont(newFont);
+                help.getContentViewer().invalidate();
+                Enumeration entries = help.getHelpNavigators();
+                while (entries.hasMoreElements()) {
+                    JHelpNavigator nav = (JHelpNavigator)entries.nextElement();
+                    nav.setFont(newFont);
+                }
+            } else if (propertyName.equals("navigatorDisplayed")) {
+		boolean display = ((Boolean)event.getNewValue()).booleanValue();
+		if (display) {
+		    // assume we're not displayed
+		    help.add("Center", splitPane);
+		} else {
+		    help.add("Center", help.getContentViewer());
+		}
+            } else if (propertyName.equals("toolbarDisplayed")) {
+		toolbar.setVisible(((Boolean)event.getNewValue()).booleanValue());
+	    }
+        }
+        
+    }
+       
+    protected HelpModel getModel() {
+        if (help == null) {
+            return null;
+        } else {
+            return help.getModel();
+        }
+    }
+    
+    /**
+     * Returns actual HelpHistoryModel
+     *
+     * @return The HelpHistoryModel
+     */
+    protected HelpHistoryModel getHistoryModel(){
+        if (help == null) {
+            return null;
+        } else {
+            return help.getHistoryModel();
+        }
+    }
+    
+    public void addNavigator(JHelpNavigator nav) {
+        debug("addNavigator");
+        navs.addElement(nav);
+        Icon icon = null;
+	// check and see if there is a presentation and if the presentation
+	// wants the view images displayed or not.
+ 	HelpSet.Presentation hsPres = help.getHelpSetPresentation();
+	if (hsPres != null) {
+	    if (hsPres.isViewImagesDisplayed()) {
+		icon = nav.getIcon();
+	    }
+	} else {
+	    // Humm, no presentation so try to get the icon
+	    icon = nav.getIcon();
+	}
+        if (icon != null) {
+            tabbedPane.addTab("", icon, nav, nav.getNavigatorLabel());
+        } else {
+            String name = nav.getNavigatorLabel();
+            if (name == null) {
+                name = "<unknown>";
+            }
+            tabbedPane.addTab(name, icon, nav);
+        }
+        nav.setVisible(false);
+        tabbedPane.setVisible(help.isNavigatorDisplayed());
+        
+        help.invalidate();
+        SwingUtilities.invokeLater(new Runnable() {
+            public void run() {
+                // The first time, arrange for the split size...
+                // This should be customizable
+                // setting a ratio at this point doesn't really work.
+                // instead we will set the point based on the ratio and the
+                // preferred sizes
+                if (dividerLocation == 0d) {
+                    Dimension dem = splitPane.getSize();
+                    // if there is a size then perform the estimate
+                    // otherwise use the default sizes
+                    if (dem.width != 0) {
+                        splitPane.setDividerLocation((int)
+                        ((double)(dem.width -
+                        splitPane.getDividerSize())
+                        * dividerLocationRatio));
+                    }
+                    dividerLocation = splitPane.getDividerLocation();
+                }
+            }
+        });
+    }
+    
+    public void removeNavigator(JHelpNavigator nav) {
+        debug("removeNavigator");
+        navs.removeElement(nav);
+        tabbedPane.remove(nav);
+        help.invalidate();
+    }
+    
+    public Enumeration getHelpNavigators() {
+        return navs.elements();
+    }
+    
+    /**
+     * Sets the current Navigator.
+     *
+     * @param navigator The navigator
+     * @exception throws InvalidNavigatorException if not one of the HELPUI
+     * navigators.
+     */
+    public void setCurrentNavigator(JHelpNavigator nav) {
+        try {
+            tabbedPane.setSelectedComponent(nav);
+        } catch (IllegalArgumentException iae) {
+            throw new IllegalArgumentException("JHelpNavigator must be added first");
+        }
+    }
+    
+    public JHelpNavigator getCurrentNavigator() {
+        return (JHelpNavigator) tabbedPane.getSelectedComponent();
+    }
+    
+    private ImageIcon getIcon(String name) {
+        return getIcon(BasicHelpUI.class, name);
+    }
+    
+    // public for now - need to reevalutate
+    public static ImageIcon getIcon(Class klass, String name) {
+        ImageIcon ig = null;
+        try {
+            ig = SwingHelpUtilities.getImageIcon(klass, name);
+        } catch (Exception ex) {
+        }
+        
+        if (debug || ig == null) {
+            System.err.println("GetIcon");
+            System.err.println("  name: "+name);
+            System.err.println("  klass: "+klass);
+            URL url = klass.getResource(name);
+            System.err.println("  URL is "+url);
+            System.err.println("  ImageIcon is "+ig);
+        }
+        return ig;
+    }
+
+    /**
+     * For printf debugging.
+     */
+    private static boolean debug = false;
+    private static void debug(String str) {
+        if (debug) {
+            System.out.println("BasicHelpUI: " + str);
+        }
+    }       
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicIndexCellRenderer.java b/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicIndexCellRenderer.java
new file mode 100644
index 0000000000000000000000000000000000000000..ea1c10071b2bdc674a638e52e7ec8f6ba5a230d0
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicIndexCellRenderer.java
@@ -0,0 +1,97 @@
+/*
+ * @(#)BasicIndexCellRenderer.java	1.21 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help.plaf.basic;
+
+import javax.help.*;
+import javax.swing.tree.*;
+import javax.swing.JTree;
+import java.awt.Component;
+import java.util.Locale;
+
+/**
+ * Cell Renderer for the index UI.
+ *
+ * @author Roger D. Brinkley
+ * @author Eduardo Pelegri-Llopart
+ * @author Stepan Marek
+ * @version   %I     10/30/06
+ */
+public class BasicIndexCellRenderer extends DefaultTreeCellRenderer {
+    
+    /**
+      * Configures the renderer based on the passed in components.
+      * The value is set from messaging the tree with
+      * <code>convertValueToText</code>, which ultimately invokes
+      * <code>toString</code> on <code>value</code>.
+      * The foreground color is set based on the selection and the icon
+      * is set based on on leaf and expanded.
+      */
+    public Component getTreeCellRendererComponent(JTree tree,
+                                                  Object value,
+						  boolean sel,
+						  boolean expanded,
+						  boolean leaf, int row,
+						  boolean hasFocus) {
+
+        // variable hasFocus was private to DefaultTreeCellRenderer since jdk1.3
+        try {
+            this.hasFocus = hasFocus;
+        } catch (IllegalAccessError e) {
+        }
+        
+    	IndexItem item
+	    = (IndexItem) ((DefaultMutableTreeNode) value).getUserObject();
+
+	String stringValue = "";
+
+	if (item != null) {
+	    stringValue = item.getName();
+	}
+
+        setText(stringValue);
+        if (sel)
+            setForeground(getTextSelectionColor());
+        else
+            setForeground(getTextNonSelectionColor());
+
+        setIcon(null);
+        
+        selected = sel;
+
+	// Set the locale of this if there is a lang value
+	if (item != null) {
+	    Locale locale = item.getLocale();
+	    if (locale != null) {
+		setLocale(locale);
+	    }
+	}
+
+	return this;
+    }
+    
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicIndexNavigatorUI.java b/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicIndexNavigatorUI.java
new file mode 100644
index 0000000000000000000000000000000000000000..843cb76a61d919f275ab1f9b1198f2041fb079bf
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicIndexNavigatorUI.java
@@ -0,0 +1,885 @@
+/*
+ * @(#)BasicIndexNavigatorUI.java	1.92 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+/*
+ * @(#) BasicIndexNavigatorUI.java 1.92 - last change made 10/30/06
+ */
+
+package javax.help.plaf.basic;
+
+import javax.help.*;
+import javax.help.plaf.HelpNavigatorUI;
+import javax.help.plaf.HelpUI;
+import javax.help.event.HelpModelListener;
+import javax.help.event.HelpModelEvent;
+import com.sun.java.help.impl.SwingWorker;
+import java.util.EventObject;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+import java.util.Locale;
+import javax.swing.BoxLayout;
+import javax.swing.ImageIcon;
+import javax.swing.JComponent;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTextField;
+import javax.swing.JTree;
+import javax.swing.RepaintManager;
+import javax.swing.SwingUtilities;
+import javax.swing.UIManager;
+import javax.swing.plaf.ComponentUI;
+import javax.swing.tree.*;
+import javax.swing.event.*;
+import java.awt.*;
+import java.awt.event.*;
+import java.io.Reader;
+import java.io.Serializable;
+import java.net.URL;
+import java.net.URLConnection;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.awt.event.ComponentEvent;
+import java.awt.event.ComponentListener;
+import javax.help.Map.ID;
+import java.text.Collator;
+import java.text.RuleBasedCollator;
+import java.lang.reflect.Method;
+
+/**
+ * The default UI for JHelpNavigator of type Index.
+ *
+ * @author Roger D. Brinkley
+ *         revised by Paul Dumais, Nov 7, 1997
+ * @author Eduardo Pelegri-Llopart
+ * @author Stepan Marek
+ * @author Richard Gregor
+ * @version   1.92     10/30/06
+ */
+
+public class BasicIndexNavigatorUI extends HelpNavigatorUI
+             implements HelpModelListener, TreeSelectionListener,
+                        PropertyChangeListener, ActionListener,
+                        ComponentListener, Serializable
+{
+    protected JHelpIndexNavigator index;
+    protected JScrollPane sp;
+    protected DefaultMutableTreeNode topNode;
+    protected JTree tree;
+    protected JTextField searchField;
+    protected RuleBasedCollator rbc;
+    protected String oldText;
+    protected DefaultMutableTreeNode currentFindNode;
+    private SwingWorker worker = null;
+
+
+    public static ComponentUI createUI(JComponent x) {
+        return new BasicIndexNavigatorUI((JHelpIndexNavigator) x);
+    }
+
+    public BasicIndexNavigatorUI(JHelpIndexNavigator b) {
+       ImageIcon icon = getImageIcon(b.getNavigatorView());
+       if (icon != null) {
+            setIcon(icon);
+       } else {
+	   setIcon(UIManager.getIcon("IndexNav.icon"));
+       }
+    }
+
+    public void installUI(JComponent c) {
+	debug ("installUI");
+
+	index = (JHelpIndexNavigator)c;
+	HelpModel model = index.getModel();
+
+	index.setLayout(new BorderLayout());
+	index.addPropertyChangeListener(this);
+        index.addComponentListener(this);
+	if (model != null) {
+	    model.addHelpModelListener(this); // for our own changes
+	}
+
+	topNode = new DefaultMutableTreeNode();
+
+	JLabel search = new JLabel(HelpUtilities.getString(HelpUtilities.getLocale(c),
+							   "index.findLabel"));
+	// should be a JButton
+	//	search.addActionListener(this);
+	searchField= new JTextField();
+	search.setLabelFor(searchField);
+	searchField.addActionListener(this);
+
+	JPanel box = new JPanel();
+	box.setLayout(new BoxLayout(box, BoxLayout.X_AXIS));
+	box.add(search);
+	box.add(searchField);
+ 
+	index.add("North", box);
+
+	tree = new JTree(topNode);
+        TreeSelectionModel tsm = tree.getSelectionModel();
+	tsm.addTreeSelectionListener(this);
+        // tsm.setSelectionMode(TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION);
+
+        tree.setShowsRootHandles(true);
+	tree.setRootVisible(false);
+
+	setCellRenderer(index.getNavigatorView(), tree);
+
+	sp = new JScrollPane();
+	sp.getViewport().add(tree);
+
+	index.add("Center", sp);
+	reloadData();
+    }
+
+    /**
+     * Sets the desired cell renderer on this tree.  This is exposed for redefinition
+     * by subclases.
+     */
+    protected void setCellRenderer(NavigatorView view, JTree tree) {
+	tree.setCellRenderer(new BasicIndexCellRenderer());
+        //in case you can use ToolTips for nodes
+        //ToolTipManager.sharedInstance().registerComponent(tree);
+    }
+    
+    public void uninstallUI(JComponent c) {
+	debug ("uninstallUI");
+	HelpModel model = index.getModel();
+
+        index.removeComponentListener(this);
+	index.removePropertyChangeListener(this);
+	TreeSelectionModel tsm = tree.getSelectionModel();
+	tsm.removeTreeSelectionListener(this);
+	index.setLayout(null);
+	index.removeAll();
+
+	if (model != null) {
+	    model.removeHelpModelListener(this);
+	}
+
+	index = null;
+    }
+
+    public Dimension getPreferredSize(JComponent c) {
+	/*
+	if (sp != null) {
+	    return ((ScrollPaneLayout)sp.getLayout()).preferredLayoutSize(sp);
+	} else {
+	    return new Dimension(200,100);
+	}
+	*/
+	return new Dimension(200,100);
+	
+    }
+
+    public Dimension getMinimumSize(JComponent c) {
+	return new Dimension(100,100);
+    }
+
+    public Dimension getMaximumSize(JComponent c) {
+	return new Dimension(Short.MAX_VALUE, Short.MAX_VALUE);
+    }
+
+    private void reloadData() {
+	debug("reloadData");
+
+	// parse the Index data into topNode
+	IndexView view = (IndexView) index.getNavigatorView();
+	if (worker != null) {
+	    // Something is still going on. Stop it and start over
+	    worker.interrupt();
+	}
+	worker = new NavSwingWorker(view);
+	worker.start(Thread.MIN_PRIORITY);
+    }
+
+    /**
+     * load the data for the navigator. Will be run on a separate
+     * thread.
+     */
+    private synchronized Object loadData(IndexView view) {
+	if (view == null) {
+	    return Boolean.FALSE;
+	}
+
+	// remove all children
+	topNode.removeAllChildren(); 
+	    
+	String mergeType = view.getMergeType();
+	    
+	Locale locale = view.getHelpSet().getLocale();
+	    
+	DefaultMutableTreeNode node = view.getDataAsTree();
+	    
+	    // Make sure the children are all handled correctly
+	MergeHelpUtilities.mergeNodeChildren(mergeType, node);
+        
+	// This is a tricky one. As you remove the entries from one node to
+	// another the list shrinks. So you can't use an Enumated list to do
+	// the move.
+	while (node.getChildCount() > 0) {
+	    topNode.add((DefaultMutableTreeNode) node.getFirstChild());
+	}
+	    
+	// Add all of the subhelpset's data
+	addSubHelpSets(view.getHelpSet());
+	return Boolean.TRUE;
+    }
+
+
+    /*
+     * Presents the data loaded in loadData. Will be run on the
+     * Swing event thread.
+     */
+    private void presentData() {
+	// reload the tree data
+	((DefaultTreeModel)tree.getModel()).reload(); 
+	    
+	setVisibility(topNode);
+
+	    
+	if (index.getModel() != null) {
+	    ID id = index.getModel().getCurrentID();
+	    if (id != null) {
+		DefaultMutableTreeNode selectedNode = findID(topNode, id);
+		selectNode(selectedNode);
+	    }
+	}
+    }
+
+    private class NavSwingWorker extends SwingWorker {
+	IndexView view;
+
+	public NavSwingWorker (IndexView view) {
+	    super();
+	    this.view = view;
+	}
+
+	public Object construct() {
+	    return loadData(view);
+	}
+
+	public void finished() {
+	    if ((Boolean)get() == Boolean.TRUE) {
+		presentData();
+	    }
+	}
+    }
+
+    /**
+     * Reloads the presentation data using new help model. Changes the navigator if new model contains
+     * view with the same name as former view
+     **/
+    private void reloadData(HelpModel model) {
+	debug("reloadData in using new model");
+ 
+       IndexView indexView = null;          
+        
+        HelpSet newHelpSet = model.getHelpSet();
+        IndexView oldView = (IndexView) index.getNavigatorView();
+        String oldName = oldView.getName();
+        NavigatorView[] navViews = newHelpSet.getNavigatorViews();
+        for(int i = 0 ; i < navViews.length; i++){
+            if((navViews[i].getName()).equals(oldName)){
+                NavigatorView tempView = navViews[i];
+                if(tempView instanceof IndexView){
+                    indexView = (IndexView) tempView;
+                    break;
+                }
+            }
+        }
+        
+	if (worker != null) {
+	    // Something is still going on. Stop it and start over
+	    worker.interrupt();
+	}
+	worker = new NavSwingWorker(indexView);
+	worker.start(Thread.MIN_PRIORITY);
+    }
+    
+    /** Adds subhelpsets
+     *
+     * @param hs The HelpSet which subhelpsets will be added
+     */
+    protected void addSubHelpSets(HelpSet hs){
+	debug ("addSubHelpSets");
+        for( Enumeration e = hs.getHelpSets(); e.hasMoreElements(); ) {
+	    HelpSet ehs = (HelpSet) e.nextElement();
+            // merge views
+            NavigatorView[] views = ehs.getNavigatorViews();
+            for(int i = 0; i < views.length; i++){
+                if(index.canMerge(views[i]))
+                    doMerge(views[i]);
+            }
+            addSubHelpSets( ehs );
+	}
+    }
+
+    /**
+     * Expands entry path and entry itself( when entry is not empty) for specific id
+     *
+     * @param target The target of entry
+     */
+   
+    private void expand(String target){
+        debug("expand called");
+        //find all nodes with certain id
+        Enumeration nodes = findNodes(target).elements();
+        DefaultMutableTreeNode node = null;
+        
+        while(nodes.hasMoreElements()){
+            node = (DefaultMutableTreeNode)nodes.nextElement();
+            debug("expandPath :"+node);
+            if(node.getChildCount() > 0){
+                DefaultMutableTreeNode child =(DefaultMutableTreeNode) node.getFirstChild();
+                TreePath path = new TreePath(child.getPath());
+                tree.makeVisible(path);
+            }
+            else{
+                TreeNode[] treeNode = node.getPath();
+                TreePath path = new TreePath(treeNode);
+                //tree.scrollPathToVisible(path);
+                tree.makeVisible(path);
+            }
+        }
+    }
+
+    /**
+     * Returns all nodes with certain id
+     *
+     * @param target The target of entry
+     *     
+     */
+    private Vector findNodes(String target){
+        Enumeration nodes = topNode.preorderEnumeration();
+        DefaultMutableTreeNode node = null;
+        Vector nodeFound = new Vector();
+        
+        while(nodes.hasMoreElements()){
+                node = (DefaultMutableTreeNode)nodes.nextElement();
+                debug(" node :"+ node.toString());
+                if(node != null){
+                    IndexItem indexItem = (IndexItem)node.getUserObject();
+                    if(indexItem == null)
+                        debug("indexItem is null");
+                    else{
+                        Map.ID id = indexItem.getID();
+                        if(id != null){
+                            debug("id name :"+id.id);
+                            debug("target :"+target);
+                            Map.ID itemID = null;
+                            try{
+                                itemID = Map.ID.create(target,index.getModel().getHelpSet());
+                            }
+                            catch(BadIDException exp){
+                                System.err.println("Not valid ID :"+target );
+                                break;
+                            }
+                            if(id.equals(itemID))
+                                nodeFound.addElement(node);
+                        }
+                    }
+                }
+        }
+                                
+        return nodeFound;
+    }
+    
+    /**
+     * Collapses entry specified by id. If entry is empty collapses it's parent.
+     *
+     * @param target The target of entry 
+     */
+      
+    private void collapse(String target){
+        Enumeration nodes = findNodes(target).elements();
+        DefaultMutableTreeNode node = null;
+        debug("collapse called");
+        
+        while(nodes.hasMoreElements()){
+            node = (DefaultMutableTreeNode)nodes.nextElement();
+            if(node.getChildCount() > 0){
+                TreeNode[] treeNode = node.getPath();
+                TreePath path = new TreePath(treeNode);
+                tree.collapsePath(path);
+                tree.collapseRow(tree.getRowForPath(path));
+            }
+            else{
+                DefaultMutableTreeNode parent =(DefaultMutableTreeNode) node.getParent();
+                TreePath path = new TreePath(parent.getPath());
+                tree.collapseRow(tree.getRowForPath(path));
+            }
+        }
+    }    
+
+
+    /**
+     * Merges in the navigational data from another IndexView.
+     */
+
+    public void doMerge(NavigatorView view) {
+	debug("merging data");
+       
+        Merge mergeObject = Merge.DefaultMergeFactory.getMerge(index.getNavigatorView(),view);
+        if(mergeObject != null) {
+            mergeObject.processMerge(topNode);
+	}
+        
+    }
+
+    /**
+     * Merges in the navigational data from another IndexView.
+     *
+     * @param view A IndexView.  Note the actual argument is a NavigatorView type
+     * so it replaces the correct NavigatorUI method.
+     */
+
+    public void merge(NavigatorView view) {
+	debug("merge");
+        doMerge(view);
+
+        //reload the tree data
+	((DefaultTreeModel)tree.getModel()).reload(); 
+	setVisibility(topNode);
+    }
+
+    /**
+     * Removes the navigational data from another IndexView.
+     *
+     * @param view An IndexView.  Note the actual argument is a NavigatorView type
+     * so it replaces the correct NavigatorUI method.
+     */
+
+    public void remove(NavigatorView view) {
+	debug("removing "+view);
+
+	remove(topNode, view.getHelpSet());
+	
+	// reload the tree data
+	((DefaultTreeModel)tree.getModel()).reload(); 
+	setVisibility(topNode);
+    }
+
+    /**
+     * Recursively removes all children of the node that have either hs or a HelpSet that
+     * is included in hs as their HelpSet data.
+     *
+     * Recursion is stopped when a node is removed.  This is because of the
+     * property of the merge mechanism.
+     *
+     * @param node The node from which to remove children.
+     * @param hs The non-null HelpSet to use.
+     */
+
+    private void remove(DefaultMutableTreeNode node,
+			HelpSet hs) {
+	debug("remove("+node+", "+hs+")");
+
+	// a simple node.children() does not work because the
+	// enumeration is voided when a child is removed
+
+	// getNextSibling() has a linear search, so we won't do that either
+
+	// Collect all to be removed
+	Vector toRemove = new Vector();
+	
+	for (Enumeration e = node.children();
+	     e.hasMoreElements(); ) {
+	    DefaultMutableTreeNode child
+		= (DefaultMutableTreeNode) e.nextElement();
+	    debug("  considering "+child);
+	    IndexItem item = (IndexItem) child.getUserObject();
+	    HelpSet chs = item.getHelpSet();
+	    debug ("chs=" + chs + " hs.contains(chs)=" + hs.contains(chs));
+	    if (chs != null &&
+		hs.contains(chs)) {
+		if (child.isLeaf()) {
+		    // if the child has no children then just remove it
+		    debug("  tagging for removal: "+child);
+		    toRemove.addElement(child); // tag to be removed...
+		} else {
+		    // be carefull here. While the child hs is one to be
+		    // removed it is possible that there are children that
+		    // are not of this hs. Attempt to remove the 
+		    // child's children first. If they're are any children left
+		    // the change the hs to be the hs of the first child
+		    remove(child, hs);
+		    if (child.isLeaf()) {
+			// no more children remove the child as well
+			debug("  tagging for removal: "+child);
+			toRemove.addElement(child); // tag to be removed...
+		    } else {
+			// nuts! There are children from different hs
+			// change the hs of the IndexItem to be the hs of the
+			// first child
+			DefaultMutableTreeNode childOne = 
+			    (DefaultMutableTreeNode) child.getFirstChild();
+			IndexItem itemOne =  (IndexItem) childOne.getUserObject();
+			item.setHelpSet(itemOne.getHelpSet());
+			debug("  orphaned children - changing hs: "+child);
+		    }
+		}
+	    } else {
+		// the child doesn't need to be removed but possibly it's
+		// children will
+		remove(child, hs);
+	    }
+	}
+	    
+	// Now remove them
+	for (int i=0; i<toRemove.size(); i++) {
+	    debug("  removing "+toRemove.elementAt(i));
+	    node.remove((DefaultMutableTreeNode) toRemove.elementAt(i));
+	}
+    }
+
+    // Make all nodes visible
+
+    private void setVisibility (DefaultMutableTreeNode node) {
+	IndexItem item = (IndexItem)node.getUserObject();
+	if (node == topNode || 
+	    (item != null && item.getExpansionType() != TreeItem.COLLAPSE)) {
+	    tree.expandPath(new TreePath(node.getPath()));
+	    if (! node.isLeaf()) {
+		int max = node.getChildCount();
+		for (int i=0; i<max; i++) {
+		    setVisibility((DefaultMutableTreeNode)node.getChildAt(i));
+		}
+	    }
+	}
+    }
+
+    // Process and idChanged event
+
+    public synchronized void idChanged(HelpModelEvent e) {
+	ID id = e.getID();
+	HelpModel helpModel = index.getModel();
+	debug("idChanged("+e+")");
+
+	if (e.getSource() != helpModel) {
+	    debug("Internal inconsistency!");
+	    debug("  "+e.getSource()+" != "+helpModel);
+	    throw new Error("Internal error");
+	}
+
+	if (id == null) {
+	    id = helpModel.getHelpSet().getCombinedMap().getClosestID(e.getURL());
+	}
+	TreePath s = tree.getSelectionPath();
+	if (s != null) {
+	    Object o = s.getLastPathComponent();
+	    // should require only a TreeNode
+	    if (o instanceof DefaultMutableTreeNode) {
+		DefaultMutableTreeNode tn = (DefaultMutableTreeNode) o;
+		IndexItem item = (IndexItem) tn.getUserObject();
+		if (item != null) {
+		    ID nId = item.getID();
+		    if (nId != null && nId.equals(id)) {
+			return;
+		    }
+		}
+	    }
+	}
+
+	DefaultMutableTreeNode node = findID(topNode, id);
+	selectNode(node);
+    }
+
+    // Note - this recursive implementation may need tuning for very large Index - epll
+
+    private DefaultMutableTreeNode findID(DefaultMutableTreeNode node, ID id) {
+	debug("findID: ("+id+")");
+	debug("  node: "+node);
+
+	// check on the id
+	if (id == null) {
+	    return null;
+	}
+	IndexItem item = (IndexItem) node.getUserObject();
+	if (item != null) {
+	    ID testID = item.getID();
+	    debug("  testID: "+testID);
+	    if (testID != null && testID.equals(id)) {
+		return node;
+	    }
+	}
+	int size = node.getChildCount();
+	for (int i=0; i<size ; i++) {
+	    DefaultMutableTreeNode tmp = 
+		(DefaultMutableTreeNode) node.getChildAt(i);
+	    DefaultMutableTreeNode test = findID(tmp, id);
+	    if (test != null) {
+		return test;
+	    }
+	}
+	return null;
+    }
+
+    /**
+     * Select a certian node
+     */
+    private void selectNode(DefaultMutableTreeNode node) {
+	if (node == null) {
+	    // node doesn't exist. Need to clear the selection.
+	    tree.clearSelection();
+	    return;
+	}
+	TreePath path = new TreePath(node.getPath());
+	tree.expandPath(path);
+	tree.setSelectionPath(path);
+	tree.scrollPathToVisible(path);
+    }
+
+    protected JHelpNavigator getHelpNavigator() {
+        return index;
+    }
+		
+    public void valueChanged(TreeSelectionEvent e) {
+
+        JHelpNavigator navigator = getHelpNavigator();
+        HelpModel helpmodel = navigator.getModel();
+
+        debug("ValueChanged: "+e);
+	debug("  model: "+helpmodel);
+
+        // send selected items into navigator
+        TreeItem[] items = null;
+        TreePath[] paths = tree.getSelectionPaths();
+        if (paths != null) {
+            items = new TreeItem[paths.length];
+            for (int i = 0; i < paths.length; i++) {
+                if (paths[i] != null) {
+                    DefaultMutableTreeNode node = (DefaultMutableTreeNode) paths[i].getLastPathComponent();
+                    items[i] = (TreeItem) node.getUserObject();
+                }
+            }
+        }
+        navigator.setSelectedItems(items);        
+        
+        // change current id only if one items is selected
+        if (items != null && items.length == 1) {
+            IndexItem item = (IndexItem) items[0];
+            if (item != null && item.getID() != null) {
+		String presentation = item.getPresentation();
+		if (presentation == null) {
+		    // This is the old way of doing things
+		    // set the currentID in the helpModel
+		    try {
+			helpmodel.setCurrentID(item.getID(), item.getName(), navigator);
+		    } catch (InvalidHelpSetContextException ex) {
+			System.err.println("BadID: "+item.getID());
+			return;
+		    }
+		} else {
+		    // using a Presentation
+		    // Get a Presentation
+		    Presentation pres;
+		    HelpSet hs = helpmodel.getHelpSet();
+		    ClassLoader loader;
+		    Class klass;
+		    Class types[] = { HelpSet.class,
+				      String.class};
+		    Object args[] = { hs,
+				      item.getPresentationName()};		
+		    try {
+			loader = hs.getLoader();
+			if (loader == null) {
+			    klass = Class.forName(presentation);
+			} else {
+			    klass = loader.loadClass(presentation);
+			}
+			Method m = klass.getMethod("getPresentation", types);
+			pres = (Presentation)m.invoke(null, args);
+		    } catch (Exception ex) {
+			throw new RuntimeException("error invoking presentation" );
+		    }
+
+		    if (pres == null) {
+			return;
+		    }
+
+		    // Minor adjustments for Windows and Popups
+		    if (pres instanceof WindowPresentation) {
+			((WindowPresentation)pres).setActivationObject(tree);
+		    }
+		    if (pres instanceof Popup) {
+			((Popup)pres).setInvokerInternalBounds(tree.getPathBounds(paths[0]));
+			((Popup)pres).setInvoker((Component)tree);
+		    }
+
+		    // set the id to be displayed
+		    try {
+			pres.setCurrentID(item.getID());
+		    } catch (InvalidHelpSetContextException ex) {
+			System.err.println("BadID: "+item.getID());
+			return;
+		    }
+
+		    // diplay the presentation
+		    pres.setDisplayed(true);
+		}
+	    }
+        }
+    }
+
+    public void propertyChange(PropertyChangeEvent event) {
+	debug("propertyChange: " + event.getSource() + " "  +
+	      event.getPropertyName());
+
+	if (event.getSource() == index) {
+	    String changeName = event.getPropertyName();
+	    if (changeName.equals("helpModel")) {
+                debug("model changed");
+		reloadData((HelpModel)event.getNewValue());
+            } else  if (changeName.equals("font")) {
+		debug ("Font change");
+		Font newFont = (Font)event.getNewValue();
+		searchField.setFont(newFont);
+		RepaintManager.currentManager(searchField).markCompletelyDirty(searchField);
+		tree.setFont(newFont);
+		RepaintManager.currentManager(tree).markCompletelyDirty(tree);
+	    } else if(changeName.equals("expand")){
+                debug("Expand change");
+                expand((String)event.getNewValue());
+            } else if(changeName.equals("collapse")){
+                debug("Collapse change");
+                collapse((String)event.getNewValue());
+            }
+	    // changes to UI property?
+	}
+    }
+
+    /**
+     * Invoked when the component's size changes.
+     */
+    public void componentResized(ComponentEvent e) {
+    }
+    
+    /**
+     * Invoked when the component's position changes.
+     */
+    public void componentMoved(ComponentEvent e) {
+    }
+    
+    /**
+     * Invoked when the component has been made visible.
+     */
+    public void componentShown(ComponentEvent e) {
+        searchField.selectAll();
+        searchField.requestFocus();
+    }
+    
+    /**
+     * Invoked when the component has been made invisible.
+     */
+    public void componentHidden(ComponentEvent e) {
+    }
+    /**
+     *  Handles Action from the JTextField component for searching.
+     */
+    public void actionPerformed(ActionEvent evt) {
+	if (evt.getSource()==searchField) {
+
+	    // get a Collator based on the component locale
+	    rbc = (RuleBasedCollator) Collator.getInstance(index.getLocale());
+ 
+	    String text = searchField.getText();
+	    if (text != null) {
+		text = text.toLowerCase();
+	    }
+	    if (oldText != null && text.compareTo(oldText) != 0) {
+		currentFindNode = null;
+	    }
+	    oldText = text;
+
+	    // find the node in the tree
+	    DefaultMutableTreeNode node = searchName(topNode, text);
+	    if (node == null) {         
+		currentFindNode = null;
+		index.getToolkit().beep();
+		return;
+	    }
+	    currentFindNode = node;
+	    
+	    //display it
+	    TreePath path = new TreePath(node.getPath());
+	    tree.scrollPathToVisible(path);
+	    tree.expandPath(path);
+	    tree.setSelectionPath(path);
+  
+	}
+    }
+
+    /**
+     *  Searches in the tree for an index item with a name that starts with String name.
+     *  Returns the node that contains the name,
+     *  returns null if no node is found.
+     */
+    private DefaultMutableTreeNode searchName(DefaultMutableTreeNode node,
+					  String name) {
+	if (currentFindNode == null) {
+	    IndexItem item = (IndexItem) node.getUserObject();
+	    if (item!=null) {
+		String itemName = item.getName();
+		if (itemName !=null) {
+		    itemName = itemName.toLowerCase();
+		    // compare the Node with the Name
+		    if (HelpUtilities.isStringInString(rbc, name, itemName)) {
+			return node;
+		    }
+		}
+	    }
+	} else {
+	    if (currentFindNode == node) {
+		currentFindNode = null;
+	    }
+	}
+
+	// travel the the rest of the tree
+	int size = node.getChildCount();
+	for (int i=0; i<size ; i++) {
+	    DefaultMutableTreeNode tmp = 
+		(DefaultMutableTreeNode) node.getChildAt(i);
+	    DefaultMutableTreeNode test = searchName(tmp, name);
+	    if (test != null) {		
+		return test;
+	    }
+	}
+	return null;
+    }
+
+    /**
+     * For printf debugging.
+     */
+    private static boolean debug = false;
+    private static void debug(String str) {
+        if (debug) {
+            System.out.println("BasicIndexNavigatorUI: " + str);
+        }
+    }
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicNativeContentViewerUI.java b/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicNativeContentViewerUI.java
new file mode 100644
index 0000000000000000000000000000000000000000..2abf301349257900f38c882463a76be1d67d561f
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicNativeContentViewerUI.java
@@ -0,0 +1,266 @@
+/*
+ * @(#)BasicNativeContentViewerUI.java	1.2 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+/*
+ * @(#) BasicNativeContentViewerUI.java 1.2 - last change made 10/30/06
+ */
+
+package javax.help.plaf.basic;
+
+import javax.help.*;
+import javax.help.plaf.HelpContentViewerUI;
+import javax.help.event.*;
+import java.util.Vector;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.Hashtable;
+import javax.swing.*;
+import javax.swing.plaf.ComponentUI;
+import javax.swing.plaf.TextUI;
+import javax.swing.border.*;
+import javax.swing.event.*;
+import java.awt.*;
+import java.awt.event.*;
+import java.net.URL;
+import java.net.MalformedURLException;
+import java.net.URLConnection;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.io.*;
+import javax.help.Map.ID;
+import org.jdesktop.jdic.browser.WebBrowser;
+
+/**
+ * A native UI for JHelpContentViewer using the native browser. 
+ *
+ * @author Roger Brinkley
+ * @version   1.2     10/30/06
+ */
+
+public class BasicNativeContentViewerUI extends HelpContentViewerUI
+implements HelpModelListener, TextHelpModelListener, PropertyChangeListener, Serializable {
+    protected JHelpContentViewer theViewer;
+    
+    private static Dimension PREF_SIZE = new Dimension(200, 300);
+    private static Dimension MIN_SIZE = new Dimension(80, 80);
+    
+    private WebBrowser html;
+    private JViewport vp;
+    
+    public static ComponentUI createUI(JComponent x) {
+        debug("createUI");
+        return new BasicNativeContentViewerUI((JHelpContentViewer) x);
+    }
+    
+    public BasicNativeContentViewerUI(JHelpContentViewer b) {
+        debug("createUI - sort of");
+    }
+    
+    public void installUI(JComponent c) {
+        debug("installUI");
+        theViewer = (JHelpContentViewer)c;
+        theViewer.setLayout(new BorderLayout());
+        
+        // listen to property changes...
+        theViewer.addPropertyChangeListener(this);
+        
+        TextHelpModel model = theViewer.getModel();
+        if (model != null) {
+            // listen to id changes...
+            model.addHelpModelListener(this);
+            // listen to highlight changes...
+            model.addTextHelpModelListener(this);
+        }
+        
+	html = new WebBrowser();
+        html.getAccessibleContext().setAccessibleName(HelpUtilities.getString(HelpUtilities.getLocale(html), "access.contentViewer"));
+	if (debug) {
+	    html.setDebug(true);
+	}
+	/**
+	 * html future additions
+	 * add any listeners here
+	 */
+
+	// if the model has a current URL then set it
+	if (model != null) {
+	    URL url = model.getCurrentURL();
+	    if (url != null) {
+		html.setURL(url);
+	    }
+	}
+
+        JScrollPane scroller = new JScrollPane();
+        scroller.setBorder(new BevelBorder(BevelBorder.LOWERED, Color.white,
+        Color.gray));
+        vp = scroller.getViewport();
+        vp.add(html);
+        vp.setBackingStoreEnabled(true);
+        
+        theViewer.add("Center", scroller);
+    }
+    
+    public void uninstallUI(JComponent c) {
+        debug("uninstallUI");
+        JHelpContentViewer viewer = (JHelpContentViewer) c;
+        viewer.removePropertyChangeListener(this);
+	/**
+	 * html future additions
+	 * remove all html listeners here - if we add any
+	 */
+        TextHelpModel model = viewer.getModel();
+        if (model != null) {
+            model.removeHelpModelListener(this);
+            model.removeTextHelpModelListener(this);
+        }
+        viewer.setLayout(null);
+        viewer.removeAll();
+    }
+    
+    public Dimension getPreferredSize(JComponent c) {
+        return PREF_SIZE;
+    }
+    
+    public Dimension getMinimumSize(JComponent c) {
+        return MIN_SIZE;
+    }
+    
+    public Dimension getMaximumSize(JComponent c) {
+        // This doesn't seem right. But I'm not sure what to do for now
+        return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
+    }
+    
+    public void idChanged(HelpModelEvent e) {
+        ID id = e.getID();
+        URL url = e.getURL();
+        TextHelpModel model = theViewer.getModel();
+        debug("idChanged("+e+")");
+        debug("  = " + id + " " + url);
+        debug("  my helpModel: "+model);
+        
+        model.setDocumentTitle(null);
+        
+	/**
+	 * html future additions
+	 * if we were doing any highlighting of the search text
+	 * code would be needed here remove all the highlights before
+	 * the new page is displayed
+	 */
+
+	html.setURL(url);
+
+        debug("done with idChanged");
+    }
+    
+    private void rebuild() {
+        debug("rebuild");
+        TextHelpModel model = theViewer.getModel();
+        if (model == null) {
+            debug("rebuild-end: model is null");
+            return;
+        }
+
+	/**
+	 * html future additions
+	 * if we were doing any highlighting the highlights would need
+	 * to be removed here
+	 */
+
+        HelpSet hs = model.getHelpSet();
+        // for glossary - not set homeID page - glossary is not synchronized
+        if(theViewer.getSynch()){
+            try {
+                Map.ID homeID = hs.getHomeID();
+                Locale locale = hs.getLocale();
+                String name = HelpUtilities.getString(locale, "history.homePage");
+                model.setCurrentID(homeID, name, (JHelpNavigator)null);
+                html.setURL(model.getCurrentURL());
+            } catch (Exception e) {
+                // ignore
+            }
+        }
+        debug("rebuild-end");
+    }
+    
+    public void propertyChange(PropertyChangeEvent event) {
+        debug("propertyChange: " + event.getPropertyName() + "\n\toldValue:" + event.getOldValue() + "\n\tnewValue:" + event.getNewValue());
+        
+        if (event.getSource() == theViewer) {
+            String changeName = event.getPropertyName();
+            if (changeName.equals("helpModel")) {
+                TextHelpModel oldModel = (TextHelpModel) event.getOldValue();
+                TextHelpModel newModel = (TextHelpModel) event.getNewValue();
+                if (oldModel != null) {
+                    oldModel.removeHelpModelListener(this);
+                    oldModel.removeTextHelpModelListener(this);
+                }
+                if (newModel != null) {
+                    newModel.addHelpModelListener(this);
+                    newModel.addTextHelpModelListener(this);
+                }
+                rebuild();
+            } else if (changeName.equals("font")) {
+                debug("font changed");
+                Font newFont = (Font)event.getNewValue();
+		/**
+		 * ~~
+		 * Put font change handling code here
+		 */
+            }else if (changeName.equals("clear")) {
+		/**
+		 * html future additions
+		 * do not know how to do this at the current time
+		 */
+                // a~~ html.setText("");
+            }else if (changeName.equals("reload")) {
+		html.refresh();
+            }
+        }
+    }
+    
+    /**
+     * Determines if highlights have changed.
+     * Collects all the highlights and marks the presentation.
+     *
+     * @param e The TextHelpModelEvent.
+     */
+    public void highlightsChanged(TextHelpModelEvent e) {
+        debug("highlightsChanged "+e);
+ 
+	// if we do anything with highlighting it would need to
+	// be handled here.
+    }
+    
+    /**
+     * For printf debugging.
+     */
+    private final static boolean debug = false;
+    private static void debug(String str) {
+        if (debug) {
+            System.out.println("NativeContentViewerUI: " + str);
+        }
+    }
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicSearchCellRenderer.java b/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicSearchCellRenderer.java
new file mode 100644
index 0000000000000000000000000000000000000000..7edfa638e05f40bf067bd1df5cd238a2a8e53ee2
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicSearchCellRenderer.java
@@ -0,0 +1,526 @@
+/*
+ * @(#)BasicSearchCellRenderer.java	1.15 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+/*
+ * @(#) BasicSearchCellRenderer.java 1.15 - last change made 10/30/06
+ */
+
+package javax.help.plaf.basic;
+
+/**
+ * TreeCellRender for JSearchNavigator.
+ *
+ * @author Roger D. Brinkley
+ * @author Eduardo Pelegri-Llopart
+ * @version   1.15     10/30/06
+ */
+
+import java.awt.*;
+import java.net.URL;
+import java.util.Locale;
+import javax.swing.*;
+import javax.swing.border.EmptyBorder;
+import javax.swing.plaf.ColorUIResource;
+import javax.swing.plaf.FontUIResource;
+import javax.swing.tree.TreeCellRenderer;
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.help.Map;
+import javax.help.Map.ID;
+import javax.help.SearchTOCItem;
+import javax.help.SearchHit;
+import javax.help.HelpUtilities;
+import javax.accessibility.AccessibleValue;
+import javax.accessibility.AccessibleContext;
+
+/**
+ * Displays an search entry in a tree.
+ *
+ * @author Roger D. Brinkley
+ * @version   1.15     10/30/06
+ */
+public class BasicSearchCellRenderer extends JPanel implements TreeCellRenderer
+{
+    /** Is the value currently selected. */
+    protected boolean selected;
+    // These two ivars will be made protected later.
+    /** True if has focus. */
+    private boolean hasFocus;
+    /** True if draws focus border around icon as well. */
+    private boolean drawsFocusBorderAroundIcon;
+
+    // Colors
+    /** Color to use for the foreground for selected nodes. */
+    protected Color textSelectionColor;
+
+    /** Color to use for the foreground for non-selected nodes. */
+    protected Color textNonSelectionColor;
+
+    /** Color to use for the background when a node is selected. */
+    protected Color backgroundSelectionColor;
+
+    /** Color to use for the background when the node is not selected. */
+    protected Color backgroundNonSelectionColor;
+
+    /** Color to use for the background when the node is not selected. */
+    protected Color borderSelectionColor;
+
+    /** Map to use for rendering included images. */
+    protected Map map;
+
+    /** Hits */
+    protected ValueJLabel hits;
+
+    /** Quality */
+    protected ValueJLabel quality;
+    
+    /** Title */
+    protected JLabel title;
+
+    /**
+      * Returns a new instance of BasicSearchCellRender.  Left alignment is
+      * set. Icons and text color are determined from the
+      * UIManager.
+      */
+    public BasicSearchCellRenderer(Map map) {
+	super();
+	this.map = map;
+
+	setTextSelectionColor(UIManager.getColor("Tree.selectionForeground"));
+	setTextNonSelectionColor(UIManager.getColor("Tree.textForeground"));
+	setBackgroundSelectionColor(UIManager.getColor("Tree.selectionBackground"));
+	setBackgroundNonSelectionColor(UIManager.getColor("Tree.textBackground"));
+	setBorderSelectionColor(UIManager.getColor("Tree.selectionBorderColor"));
+	Object value = UIManager.get("Tree.drawsFocusBorderAroundIcon");
+	drawsFocusBorderAroundIcon = (value != null && ((Boolean)value).
+				      booleanValue());
+
+	setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
+	hits = new ValueJLabel();
+	hits.setHorizontalAlignment(JLabel.LEFT);
+	quality = new ValueJLabel();
+	title = new JLabel(); 
+	title.setFont(getFont());
+	title.setHorizontalAlignment(JLabel.LEFT);
+	add(Box.createRigidArea(new Dimension(4,0)));
+	add(quality);
+	add(Box.createRigidArea(new Dimension(4,0)));
+	add(hits);
+	add(Box.createRigidArea(new Dimension(4,0)));
+	add(title);
+
+    }
+
+
+    /**
+      * Sets the color the text is drawn with when the node is selected.
+      */
+    public void setTextSelectionColor(Color newColor) {
+	textSelectionColor = newColor;
+    }
+
+    /**
+      * Returns the color the text is drawn with when the node is selected.
+      */
+    public Color getTextSelectionColor() {
+	return textSelectionColor;
+    }
+
+    /**
+      * Sets the color the text is drawn with when the node is not selected.
+      */
+    public void setTextNonSelectionColor(Color newColor) {
+	textNonSelectionColor = newColor;
+    }
+
+    /**
+      * Returns the color the text is drawn with when the node is not selected.
+      */
+    public Color getTextNonSelectionColor() {
+	return textNonSelectionColor;
+    }
+
+    /**
+      * Sets the color to use for the background if the node is selected.
+      */
+    public void setBackgroundSelectionColor(Color newColor) {
+	backgroundSelectionColor = newColor;
+    }
+
+
+    /**
+      * Returns the color to use for the background if the node is selected.
+      */
+    public Color getBackgroundSelectionColor() {
+	return backgroundSelectionColor;
+    }
+
+    /**
+      * Sets the background color to be used for unselected nodes.
+      */
+    public void setBackgroundNonSelectionColor(Color newColor) {
+	backgroundNonSelectionColor = newColor;
+    }
+
+    /**
+      * Returns the background color to be used for unselected nodes.
+      */
+    public Color getBackgroundNonSelectionColor() {
+	return backgroundNonSelectionColor;
+    }
+
+    /**
+      * Sets the color to use for the border.
+      */
+    public void setBorderSelectionColor(Color newColor) {
+	borderSelectionColor = newColor;
+    }
+
+    /**
+      * Returns the the border color.
+      */
+    public Color getBorderSelectionColor() {
+	return borderSelectionColor;
+    }
+
+    /**
+     * Subclassed to only accept the font if it is not a FontUIResource.
+     */
+    public void setFont(Font font) {
+	if(font instanceof FontUIResource) {
+	    font = null;
+	}
+	if (font != null) {
+	    if (title != null) {
+		title.setFont(font);
+	    }
+	}
+	super.setFont(font);
+    }
+
+    /**
+     * Subclassed to only accept the color if it is not a ColorUIResource.
+     */
+    public void setBackground(Color color) {
+	if(color instanceof ColorUIResource)
+	    color = null;
+	super.setBackground(color);
+    }
+
+    /**
+      * Configures the renderer based on the components passed in.
+      * Sets the value from messaging value with toString().
+      * The foreground color is set based on the selection and the icon
+      * is set based on on leaf and expanded.
+      */
+    public Component getTreeCellRendererComponent(JTree tree, Object value,
+						  boolean sel,
+						  boolean expanded,
+						  boolean leaf, int row,
+						  boolean hasFocus) {
+	SearchTOCItem item = 
+	    (SearchTOCItem) ((DefaultMutableTreeNode) value).getUserObject();
+	    
+	String stringValue = "";
+
+	if (item != null) {
+	    stringValue = item.getName();
+	}
+
+	if (sel) {
+	    hits.setForeground(getTextNonSelectionColor());
+	    title.setForeground(getTextSelectionColor());
+	    title.setBackground(getBackgroundSelectionColor());
+	} else {
+	    Color bColor = getBackgroundNonSelectionColor();
+	    if(bColor == null)
+		bColor = getBackground();
+	    hits.setForeground(getTextNonSelectionColor());
+	    title.setForeground(getTextNonSelectionColor());
+	    title.setBackground(bColor);
+	}
+
+	Locale locale = Locale.getDefault();
+
+	// Set the locale of this if there is a lang value
+	if (item != null) {
+	    locale = item.getLocale();
+	    if (locale != null) {
+		setLocale(locale);
+	    }
+	}
+
+	if (item != null) {
+	    // Set the hit count
+	    int hitCount = item.hitCount();
+	    hits.setText(String.valueOf(hitCount));
+	    hits.setAccessibility(null, 
+				  HelpUtilities.getString(locale, "search.hitDesc"),
+				  new Integer(hitCount),
+				  new Integer(hitCount),
+				  new Integer(hitCount));
+
+	    String qualityLevel=null;
+	    // Set the quality index
+	    double penalty = item.getConfidence();
+	    if (penalty < 1) {
+		quality.setIcon(high);
+		qualityLevel = HelpUtilities.getString(locale, "search.high");
+	    } else if (penalty < 5) {
+		quality.setIcon(medhigh);
+		qualityLevel = HelpUtilities.getString(locale, "search.midhigh");
+	    } else if (penalty < 12.5) {
+		quality.setIcon(med);
+		qualityLevel = HelpUtilities.getString(locale, "search.mid");
+	    } else if (penalty < 25) {
+		quality.setIcon(medlow);
+		qualityLevel = HelpUtilities.getString(locale, "search.midlow");
+	    } else {
+		quality.setIcon(low);
+		qualityLevel = HelpUtilities.getString(locale, "search.low");
+	    }
+
+	    quality.setAccessibility(qualityLevel, 
+				     HelpUtilities.getString(locale, "search.qualityDesc"),
+				     new Double(penalty),
+				     new Double(penalty),
+				     new Double(penalty));
+	    
+	    // Finally set the title
+	    title.setText(stringValue);
+	}
+
+	selected = sel;
+	this.hasFocus = hasFocus;
+	return this;
+    }
+
+    /**
+      * Paints the value.  The background is filled based on selected color.
+      */
+    public void paint(Graphics g) {
+	Color bColor;
+
+	if(selected) {
+	    bColor = getBackgroundSelectionColor();
+	} else {
+	    bColor = getBackgroundNonSelectionColor();
+	    if(bColor == null)
+		bColor = getBackground();
+	}
+	int imageOffset = -1;
+	if(bColor != null) {
+
+	    imageOffset = getLabelStart();
+	    g.setColor(bColor);
+	    Dimension size = getSize();
+	    g.fillRect(imageOffset, 0, size.width - 1 - imageOffset,
+		       size.height);
+	}
+	if (hasFocus) {
+	    if (drawsFocusBorderAroundIcon) {
+		imageOffset = 0;
+	    }
+	    else if (imageOffset == -1) {
+		imageOffset = getLabelStart();
+	    }
+	    g.setColor(getBorderSelectionColor());
+	    g.drawRect(imageOffset, 0, getWidth() - 1 - imageOffset,
+		       getHeight() - 1);
+	}
+	// call paintChildren and not paint so we don't
+	// erase everyting we've already done.
+	super.paintChildren(g);
+
+    }
+
+    private int getLabelStart() {
+	return title.getX() - 1;
+    }
+
+    /**
+     * Overrides <code>JComponent.getPreferredSize</code> to
+     * return slightly taller preferred size value.
+     */
+    public Dimension getPreferredSize() {
+	Dimension        retDimension = super.getPreferredSize();
+	int width = 0;
+	int height = 0;
+
+	// Set the initial height;
+	if (retDimension != null) {
+	    height = retDimension.height;
+	}
+	
+	// The the insets
+	Insets insets = getInsets();
+	width += insets.left + insets.right;
+
+	// Add the width of the quality
+	width += 4;
+	Dimension size;
+	size = quality.getPreferredSize();
+	width += size.width;
+	height = Math.max(height, size.height + insets.top + insets.bottom);
+
+	// Add the width of quantity
+	width += 4;
+	size = hits.getPreferredSize();
+	width += size.width;
+	height = Math.max(height, size.height + insets.top + insets.bottom);
+
+	// Add the width of titl
+	width += 4;
+	size = title.getPreferredSize();
+	width += size.width;
+	height = Math.max(height, size.height + insets.top + insets.bottom);
+
+	// Add 3 to the width for good measure
+	width += 3;
+
+	if(retDimension != null)
+	    retDimension = new Dimension(retDimension.width + 3,
+					 retDimension.height);
+	retDimension.setSize(width, height);
+	return retDimension;
+    }
+
+    // icons used for the BasicSearchCellRender
+    private static Icon high = UIManager.getIcon("SearchHigh.icon");
+    private static Icon medhigh = UIManager.getIcon("SearchMedHigh.icon");
+    private static Icon med = UIManager.getIcon("SearchMed.icon");
+    private static Icon medlow = UIManager.getIcon("SearchMedLow.icon");
+    private static Icon low = UIManager.getIcon("SearchLow.icon");
+
+    private class ValueJLabel extends JLabel {
+
+	String accessName;
+	String accessDesc;
+	Number accessValue;
+	Number minValue;
+	Number maxValue;
+
+	public void setAccessibility (String accessName, String accessDesc, 
+				      Number accessValue, Number minValue, 
+				      Number maxValue) {
+	    this.accessName = accessName;
+	    this.accessDesc = accessDesc;
+	    this.accessValue = accessValue;
+	    this.minValue = minValue;
+	    this.maxValue = maxValue;
+	}
+
+
+	/////////////////
+	// Accessibility support
+	////////////////
+	
+	/**
+	 * Get the AccessibleContext associated with this JComponent
+	 *
+	 * @return the AccessibleContext of this JComponent
+	 */
+	public AccessibleContext getAccessibleContext() {
+	    if (accessibleContext == null) {
+		accessibleContext = new AccessibleValueJLabel();
+	    }
+	    accessibleContext.setAccessibleDescription(accessDesc);
+	    accessibleContext.setAccessibleName(accessName);
+	    return accessibleContext;
+	}
+
+	/**
+	 * The class used to obtain the accessible role for this object.
+	 * <p>
+	 * <strong>Warning:</strong>
+	 * Serialized objects of this class will not be compatible with
+	 * future Swing releases.  The current serialization support is	 appropriate
+	 * for short term storage or RMI between applications running the same
+	 * version of Swing.  A future release of Swing will provide support for
+	 * long term persistence.
+	 */
+	protected class AccessibleValueJLabel extends AccessibleJLabel implements AccessibleValue {
+
+
+	    public AccessibleValue getAccessibleValue() {
+		return this;
+	    }
+
+	    /**
+	     * Get the value of this object as a Number.  
+	     * If the value has not  been
+	     * set, the return value will be null.
+	     *
+	     * @return value of the object
+	     * @see #setCurrentAccessibleValue
+	     */
+	    public Number getCurrentAccessibleValue() {
+		return accessValue;
+	    }
+
+	    /**
+	     * Set the value of this object as a Number.
+	     *
+	     * @return True if the value was set; else False
+	     * @see #getCurrentAccessibleValue
+	     */
+	    public boolean setCurrentAccessibleValue(Number n) {
+		return false;       // I assume the value can't be set
+	    }
+
+	    /**
+	     * Get the minimum value of this object as a Number.
+	     *
+	     * @return Minimum value of the object; null if this object does not
+	     * have a minimum value
+	     * @see #getMaximumAccessibleValue
+	     */
+	    public Number getMinimumAccessibleValue() {
+		return minValue;
+	    }
+
+	    /**
+	     * Get the maximum value of this object as a Number.
+	     *
+	     * @return Maximum value of the object; null if this object does not
+	     * have a maximum value
+	     * @see #getMinimumAccessibleValue
+	     */
+	    public Number getMaximumAccessibleValue() {
+		return maxValue;
+	    }
+	}
+    }
+    
+    /**
+     * For printf debugging.
+     */
+    private static boolean debug = false;
+    private static void debug(String str) {
+        if (debug) {
+            System.out.println("BasicSearchCellRenderer: " + str);
+        }
+    }
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicSearchNavigatorUI.java b/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicSearchNavigatorUI.java
new file mode 100644
index 0000000000000000000000000000000000000000..0293d3f6378027aecfc0057fae65d21f8adfb0fa
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicSearchNavigatorUI.java
@@ -0,0 +1,768 @@
+/*
+ * @(#)BasicSearchNavigatorUI.java	1.86 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+/*
+ * @(#) BasicSearchNavigatorUI.java 1.86 - last change made 10/30/06
+ */
+
+package javax.help.plaf.basic;
+
+/**
+ * UI for Search Navigator of type JHelpListNavigator.
+ *
+ * @author Roger D. Brinkley
+ * @author Eduardo Pelegri-Llopart
+ * @author Stepan Marek
+ * @author Richard Gregor
+ * @version   1.86     10/30/06
+ */
+import javax.help.*;
+import javax.help.search.*;
+import javax.help.plaf.HelpNavigatorUI;
+import javax.help.event.HelpModelListener;
+import javax.help.event.HelpModelEvent;
+import javax.help.search.SearchListener;
+import javax.help.search.SearchEvent;
+import java.util.EventObject;
+import java.util.Vector;
+import java.util.Enumeration;
+import java.net.URL;
+import javax.swing.*;
+import javax.swing.tree.*;
+import javax.swing.plaf.ComponentUI;
+import javax.swing.event.*;
+import java.awt.*;
+import java.awt.event.*;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.awt.event.ComponentEvent;
+import java.awt.event.ComponentListener;
+import java.net.MalformedURLException;
+import javax.help.DefaultHelpModel.DefaultHighlight;
+import javax.help.Map.ID;
+
+public class BasicSearchNavigatorUI extends HelpNavigatorUI 
+             implements HelpModelListener, SearchListener, 
+             PropertyChangeListener, TreeSelectionListener, 
+             ComponentListener
+{
+    protected JHelpSearchNavigator searchnav;
+    protected JScrollPane sp;
+    protected JTree tree;
+    protected DefaultMutableTreeNode topNode;
+    protected JTextField searchparams;
+    protected boolean displayOptions;
+    protected SearchEngine helpsearch;
+    protected SearchQuery searchquery;
+    protected DefaultMutableTreeNode lastTOCnode;
+    private   HelpSet newHelpSet;
+
+    public static ComponentUI createUI(JComponent x) {
+        return new BasicSearchNavigatorUI((JHelpSearchNavigator) x);
+    }
+
+    public BasicSearchNavigatorUI(JHelpSearchNavigator b) {
+        ImageIcon icon = getImageIcon(b.getNavigatorView());
+        if (icon != null) {
+            setIcon(icon);
+        } else {
+	    setIcon(UIManager.getIcon("SearchNav.icon"));
+	}
+    }
+
+    ActionListener searchAction = new SearchActionListener();
+    private Cursor paramCursor;
+    private Cursor treeCursor;
+    private Cursor waitCursor=null;
+
+    class SearchActionListener implements ActionListener {
+	public synchronized void actionPerformed(ActionEvent e) {
+	    HelpModel helpmodel = searchnav.getModel();
+	    try {
+		if (paramCursor == null) {
+		    paramCursor = searchparams.getCursor();
+		}
+		if (treeCursor == null) {
+		    treeCursor = tree.getCursor();
+		}
+		if (waitCursor == null) {
+		    waitCursor = Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR);
+		}
+		searchparams.setCursor(waitCursor);
+		tree.setCursor(waitCursor);
+                
+            	if (helpsearch == null) {
+                    debug("helpsearch is null");
+		    helpsearch = searchnav.getSearchEngine();
+		    searchquery = helpsearch.createQuery();
+		    searchquery.addSearchListener(BasicSearchNavigatorUI.this);
+		}
+		debug("click on search w/: "+searchparams.getText());
+		if (searchquery.isActive()) {
+		    searchquery.stop();
+		}
+		searchquery.start(searchparams.getText(),searchnav.getLocale());
+	    } catch (Exception e2) {
+		searchparams.setCursor(paramCursor);
+		tree.setCursor(treeCursor);
+		// more work needed here
+		e2.printStackTrace();
+		// 2 beeps
+		searchnav.getToolkit().beep();
+		searchnav.getToolkit().beep();
+	    }
+	}
+    }
+
+    public void installUI(JComponent c) {
+	searchnav = (JHelpSearchNavigator)c;
+	HelpModel helpmodel = searchnav.getModel();
+
+	searchnav.setLayout(new BorderLayout());
+	searchnav.addPropertyChangeListener(this);
+        searchnav.addComponentListener(this);
+	if (helpmodel != null) {
+	    helpmodel.addHelpModelListener(this);
+	}
+
+	JLabel search = new JLabel(HelpUtilities.getString(HelpUtilities.getLocale(c),
+							   "search.findLabel"));
+	searchparams = new JTextField ("", 20);
+	search.setLabelFor(searchparams);
+	searchparams.addActionListener(searchAction);
+
+	JPanel box = new JPanel();
+	box.setLayout(new BoxLayout(box, BoxLayout.X_AXIS));
+	box.add(search);
+	box.add(searchparams);
+
+	searchnav.add ("North", box);
+	topNode = new DefaultMutableTreeNode();
+	lastTOCnode = null;
+	tree = new JTree(topNode);
+            // public String convertValueToText(Object val
+	TreeSelectionModel tsm = tree.getSelectionModel();
+	tsm.addTreeSelectionListener(this);
+	tree.setShowsRootHandles(false);
+	tree.setRootVisible(false);
+	sp = new JScrollPane();
+	sp.getViewport().add(tree);
+	searchnav.add("Center", sp);
+	reloadData();
+    }
+
+    public void uninstallUI(JComponent c) {
+	HelpModel helpmodel = searchnav.getModel();
+
+        searchnav.removeComponentListener(this);
+	searchnav.removePropertyChangeListener(this);
+	TreeSelectionModel tsm = tree.getSelectionModel();
+	tsm.removeTreeSelectionListener(this);
+	searchnav.setLayout(null);
+	searchnav.removeAll();
+
+	if (helpmodel != null) {
+	    helpmodel.removeHelpModelListener(this);
+	}
+	searchnav = null;
+    }
+
+    public Dimension getPreferredSize(JComponent c) {
+	/*
+	if (sp != null) {
+	    return ((ScrollPaneLayout)sp.getLayout()).preferredLayoutSize(sp);
+	} else {
+	    return new Dimension(200,100);
+	}
+	*/
+	return new Dimension(200,100);
+    }
+
+    public Dimension getMinimumSize(JComponent c) {
+	if (sp != null) {
+	    return ((ScrollPaneLayout)sp.getLayout()).minimumLayoutSize(sp);
+	} else {
+	    return new Dimension(100,100);
+	}
+    }
+
+    public Dimension getMaximumSize(JComponent c) {
+	return new Dimension(Short.MAX_VALUE, Short.MAX_VALUE);
+    }
+
+    /**
+     * Indicates that there is new search data to use.
+     */
+    private void reloadData() {
+	helpsearch = null;
+	setCellRenderer(searchnav.getNavigatorView(), tree);
+        // add all subhelpsets
+	HelpModel model = searchnav.getModel();
+	if (model != null) {
+	    addSubHelpSets(model.getHelpSet());
+	}
+    }
+    
+    /**
+     * Reloads data from new model, creates new search engine to search in new model if model
+     * contains view with the same name
+     **/ 
+    private void reloadData(HelpModel model) {
+	debug("reloadData using new model");
+        helpsearch = null;
+        SearchView view = null;          
+        
+        newHelpSet = model.getHelpSet();
+        SearchView oldView = (SearchView) searchnav.getNavigatorView();
+        String oldName = oldView.getName();
+        NavigatorView[] navViews = newHelpSet.getNavigatorViews();
+        for(int i = 0 ; i < navViews.length; i++){
+            if((navViews[i].getName()).equals(oldName)){
+                NavigatorView tempView = navViews[i];
+                if(tempView instanceof SearchView){
+                    view = (SearchView) tempView;
+                    break;
+                }
+            }
+        }
+        
+        if(view == null)
+            return;
+                         
+        topNode.removeAllChildren();
+        searchnav.setSearchEngine(new MergingSearchEngine(view));
+        
+ 
+        setCellRenderer(view, tree);
+        // add all subhelpsets
+        addSubHelpSets(newHelpSet);
+
+    }
+    /** Adds subhelpsets
+     *
+     * @param hs The HelpSet which subhelpsets will be added
+     */
+    protected void addSubHelpSets(HelpSet hs){
+        for( Enumeration e = hs.getHelpSets(); e.hasMoreElements(); ) {
+	    HelpSet ehs = (HelpSet) e.nextElement();
+            // merge views
+            NavigatorView[] views = ehs.getNavigatorViews();
+            for(int i = 0; i < views.length; i++){
+                if(searchnav.canMerge(views[i]))
+                    searchnav.merge(views[i]);
+            }
+            addSubHelpSets( ehs );
+	}
+    }
+
+    /**
+     * Merges in the navigational data from another NavigatorView. 
+     */
+
+    public void merge(NavigatorView view) {
+	debug("merging "+view);
+
+	// redo the search if necessary
+	String text = searchparams.getText();
+	if (text != null && text.length() != 0) {
+	    searchAction.actionPerformed(new ActionEvent(searchparams,
+							 ActionEvent.ACTION_PERFORMED,
+							 ""));
+	}
+    }
+
+    /**
+     * Removes the navigational data from another NavigatorView. 
+     */
+
+    public void remove(NavigatorView view) {
+	debug("removing "+view);
+
+	// redo the search if necessary
+	if (searchparams.getText() != null) {
+	    searchAction.actionPerformed(new ActionEvent(searchparams,
+							 ActionEvent.ACTION_PERFORMED,
+							 ""));
+	}
+    }
+
+    /**
+     * Setd the desired cell renderer on this tree.  This is exposed for redefinition
+     * by subclases.
+     */
+    protected void setCellRenderer(NavigatorView view, JTree tree) {
+	if (view == null) {
+	    return;
+	}
+	Map map = view.getHelpSet().getCombinedMap();
+	tree.setCellRenderer(new BasicSearchCellRenderer(map));
+    }
+
+    /**
+     * Processes an idChanged event. Search is different from all other
+     * navigators in that you while search tree is synchronized 
+     * the highlighting doesn't occur unless selected from the search
+     * navigator.
+     */
+
+    public void idChanged(HelpModelEvent e) {
+ 	ID id = e.getID();
+	URL url = e.getURL();
+	HelpModel helpModel = searchnav.getModel();
+	debug("idChanged("+e+")");
+
+	if (e.getSource() != helpModel) {
+	    debug("Internal inconsistency!");
+	    debug("  "+e.getSource()+" != "+helpModel);
+	    throw new Error("Internal error");
+	}
+
+	TreePath s = tree.getSelectionPath();
+	if (s != null) {
+	    Object o = s.getLastPathComponent();
+	    // should require only a TreeNode
+	    if (o instanceof DefaultMutableTreeNode) {
+		DefaultMutableTreeNode tn = (DefaultMutableTreeNode) o;
+		SearchTOCItem item = (SearchTOCItem) tn.getUserObject();
+		if (item != null) {
+		    ID nId = item.getID();
+		    if (nId != null && nId.equals(id)) {
+			return;
+		    }
+		}
+	    }
+	}
+
+	DefaultMutableTreeNode node = findIDorURL(topNode, id, url);
+	if (node == null) {
+	    // node doesn't exist. Need to clear the selection.
+	    debug ("node didn't exist");
+	    tree.clearSelection();
+	    return;
+	}
+	TreePath path = new TreePath(node.getPath());
+	tree.expandPath(path);
+	tree.setSelectionPath(path);
+	tree.scrollPathToVisible(path);
+    }
+
+    protected JHelpNavigator getHelpNavigator() {
+        return searchnav;
+    }
+    
+    /**
+     * A value has changed.  This is used as a TreeSelectionListener.
+     */
+    public void valueChanged(TreeSelectionEvent e) {
+
+        JHelpNavigator navigator = getHelpNavigator();
+        HelpModel helpmodel = navigator.getModel();
+
+        debug("ValueChanged: "+e);
+	debug("  model: "+helpmodel);
+
+        // send selected items into navigator
+        TreeItem[] items = null;
+        TreePath[] paths = tree.getSelectionPaths();
+        if (paths != null) {
+            items = new TreeItem[paths.length];
+            for (int i = 0; i < paths.length; i++) {
+                if (paths[i] != null) {
+                    DefaultMutableTreeNode node = (DefaultMutableTreeNode) paths[i].getLastPathComponent();
+                    items[i] = (TreeItem) node.getUserObject();
+                }
+            }
+        }
+        navigator.setSelectedItems(items);
+
+        // change current id only if one items is selected
+        if (items != null && items.length == 1) {
+            SearchTOCItem item = (SearchTOCItem)items[0];
+            if (item != null) {
+                if  (item.getID() != null) {
+                    try {
+                        // navigator.setCurrentID(item.getID());
+                        helpmodel.setCurrentID(item.getID(), item.getName(), navigator);
+                    } catch (InvalidHelpSetContextException ex) {
+                        System.err.println("BadID: "+item.getID());
+                        return;
+                    }
+                } else if (item.getURL() != null) {
+                    // navigator.setCurrentURL(item.getURL());
+                    helpmodel.setCurrentURL(item.getURL(), item.getName(), navigator);
+                } else {
+                    // no ID, no URL
+                    return;
+                }
+                if (helpmodel instanceof TextHelpModel) {
+                    DefaultHighlight h[] = new DefaultHighlight[item.hitCount()];
+                    int i = 0;
+                    Enumeration enum1 = item.getSearchHits();
+                    while (enum1.hasMoreElements()) {
+                        SearchHit info = (SearchHit) enum1.nextElement();
+                        h[i] = new DefaultHighlight(info.getBegin(), info.getEnd());
+                        i++;
+                    }
+                    // using setHighlights() instead of removeAll + add
+                    // avoids one highlighting event
+                    ((TextHelpModel)helpmodel).setHighlights(h);
+                }
+            }
+        }
+    }
+
+    public void propertyChange(PropertyChangeEvent event) {
+	debug(this + " " + "propertyChange: " + event.getSource() + " "  +
+	      event.getPropertyName());
+
+	if (event.getSource() == searchnav) {
+	    String changeName = event.getPropertyName();
+	    if (changeName.equals("helpModel")) {
+                
+               reloadData((HelpModel)event.getNewValue());
+               
+	    } else  if (changeName.equals("font")) {
+		debug ("Font change");
+		Font newFont = (Font)event.getNewValue();
+		searchparams.setFont(newFont);
+		RepaintManager.currentManager(searchparams).markCompletelyDirty(searchparams);
+		tree.setFont(newFont);
+		RepaintManager.currentManager(tree).markCompletelyDirty(tree);
+	    }
+	    // changes to UI property?
+	}
+    }
+
+    /**
+     * Invoked when the component's size changes.
+     */
+    public void componentResized(ComponentEvent e) {
+    }
+    
+    /**
+     * Invoked when the component's position changes.
+     */
+    public void componentMoved(ComponentEvent e) {
+    }
+    
+    /**
+     * Invoked when the component has been made visible.
+     */
+    public void componentShown(ComponentEvent e) {
+        searchparams.selectAll();
+        searchparams.requestFocus();
+    }
+    
+    /**
+     * Invoked when the component has been made invisible.
+     */
+    public void componentHidden(ComponentEvent e) {
+    }
+    
+    // Note - this recursive implementation may need tuning for very large TOC - epll
+
+    private DefaultMutableTreeNode findIDorURL(DefaultMutableTreeNode node, 
+					       ID id, URL url) {
+	SearchTOCItem item = (SearchTOCItem) node.getUserObject();
+	if (item != null) {
+	    ID testID = item.getID();
+	    if (testID != null && id != null && testID.equals(id)) {
+		return node;
+	    } else {
+		URL testURL = item.getURL();
+		if (testURL != null && url != null && url.sameFile(testURL)) {
+		    return node;
+		}
+	    }
+	}
+	int size = node.getChildCount();
+	for (int i=0; i<size ; i++) {
+	    DefaultMutableTreeNode tmp = 
+		(DefaultMutableTreeNode) node.getChildAt(i);
+	    DefaultMutableTreeNode test = findIDorURL(tmp, id, url);
+	    if (test != null) {
+		return test;
+	    }
+	}
+	return null;
+    }
+		
+    // reorder the nodes 
+    private void reorder (Vector nodes) {
+
+	debug ("reorder nodes");
+
+	// remove all the children of topNode (they'll be added back later)
+	topNode.removeAllChildren();
+
+	// Create an array of the elements for sorting & copy the elements
+	// into the array.
+	DefaultMutableTreeNode[] array = new DefaultMutableTreeNode[nodes.size()];
+	nodes.copyInto(array);
+
+	// Sort the array (Quick Sort)
+	quickSort(array, 0, array.length - 1);
+
+	// Reload the topNode. Everthing is in order now.
+	for (int i=0; i < array.length ; i++) {
+	    topNode.add((DefaultMutableTreeNode)array[i]);
+	}
+
+	// Tell the tree to repaint itself
+	((DefaultTreeModel)tree.getModel()).reload(); 
+	tree.invalidate();
+	tree.repaint();
+    }
+
+    /** This is a version of C.A.R Hoare's Quick Sort
+    * algorithm.  This will handle arrays that are already
+    * sorted, and arrays with duplicate keys.<BR>
+    *
+    * If you think of a one dimensional array as going from
+    * the lowest index on the left to the highest index on the right
+    * then the parameters to this function are lowest index or
+    * left and highest index or right.  The first time you call
+    * this function it will be with the parameters 0, a.length - 1.
+    *
+    * @param a       a DefaultMutableTreeNode array
+    * @param lo0     left boundary of array partition
+    * @param hi0     right boundary of array partition
+    */
+    void quickSort(DefaultMutableTreeNode a[], int lo0, int hi0) {
+	int lo = lo0;
+	int hi = hi0;
+	int mid;
+
+	if ( hi0 > lo0)
+	    {
+
+		/* Arbitrarily establishing partition element as the midpoint of
+		 * the array.
+		 */
+		mid = ( lo0 + hi0 ) / 2;
+
+		// loop through the array until indices cross
+		while( lo <= hi )
+		    {
+			/* find the first element that is greater than or equal to
+			 * the partition element starting from the left Index.
+			 */
+	     
+			while( ( lo < hi0 ) && ( compare(a[lo],a[mid]) > 0 ))
+			    ++lo;
+
+			/* find an element that is smaller than or equal to
+			 * the partition element starting from the right Index.
+			 */
+			while( ( hi > lo0 ) && ( compare(a[hi],a[mid]) < 0 ))
+			    --hi;
+
+			// if the indexes have not crossed, swap
+			if( lo <= hi )
+			    {
+				swap(a, lo, hi);
+				++lo;
+				--hi;
+			    }
+		    }
+
+		/* If the right index has not reached the left side of array
+		 * must now sort the left partition.
+		 */
+		if( lo0 < hi )
+		    quickSort( a, lo0, hi );
+
+		/* If the left index has not reached the right side of array
+		 * must now sort the right partition.
+		 */
+		if( lo < hi0 )
+		    quickSort( a, lo, hi0 );
+
+	    }
+    }
+
+    private void swap(DefaultMutableTreeNode a[], int i, int j)
+    {
+	DefaultMutableTreeNode T;
+	T = a[i];
+	a[i] = a[j];
+	a[j] = T;
+
+    }
+
+    private int compare (DefaultMutableTreeNode node1, 
+			 DefaultMutableTreeNode node2) {
+	SearchTOCItem item1, item2;
+	double confidence1, confidence2;
+	int hits1, hits2;
+
+	item1 = (SearchTOCItem) node1.getUserObject();
+	confidence1 = item1.getConfidence();
+	hits1 = item1.hitCount();
+
+	item2 = (SearchTOCItem) node2.getUserObject();
+	confidence2 = item2.getConfidence();
+	hits2 = item2.hitCount();
+
+	// confidence is a penality. The lower the better
+	if (confidence1 > confidence2) {
+	    // node1 is less than node2
+	    return -1;
+	} else if (confidence1 < confidence2) {
+	    // node1 is greater than node2
+	    return 1;
+	} else {
+	    // confidences are the same check the hits
+	    if (hits1 < hits2) {
+		// node1 is less than node2
+		return -1;
+	    } else if (hits1 > hits2) {
+		// node2 is greater than node2
+		return 1;
+	    }
+	}
+	// nodes1 and nodes2 are equivalent
+	return 0;
+
+    }
+
+    public synchronized void itemsFound(SearchEvent e) {
+	SwingUtilities.invokeLater(new SearchItemsFound(e));
+    }
+
+    class SearchItemsFound implements Runnable {
+
+	SearchEvent e;
+	
+	SearchItemsFound (SearchEvent e) {
+	    this.e = e;
+	}
+
+	public void run() {
+	    SearchTOCItem tocitem;
+	    Vector nodes = new Vector();
+	    
+	    // Add all the children of the topnode to the Vector of nodes.
+	    Enumeration children = topNode.children();
+	    while (children.hasMoreElements()) {
+		DefaultMutableTreeNode node = (DefaultMutableTreeNode) children.nextElement();
+		nodes.addElement(node);
+	    }
+	    
+	    debug ("items found");
+	    HelpModel helpmodel = searchnav.getModel();
+	    HelpSet hs = helpmodel.getHelpSet();
+	    debug("hs:"+hs.toString());
+	    Map map = hs.getCombinedMap();
+	    Enumeration itemEnum = e.getSearchItems();
+	    while (itemEnum.hasMoreElements()) {
+		SearchItem item = (SearchItem) itemEnum.nextElement();
+		debug("  item: "+item);
+		URL url;
+		try {
+		    url = new URL(item.getBase(), item.getFilename());
+		} catch (MalformedURLException me) {
+		    System.err.println ("Failed to create URL from " + item.getBase() + "|" +
+					item.getFilename());
+		    continue;
+		}
+		boolean foundNode = false;
+		DefaultMutableTreeNode node = null;
+		Enumeration nodesEnum = nodes.elements();
+		while (nodesEnum.hasMoreElements()) {
+		    node = (DefaultMutableTreeNode)nodesEnum.nextElement();
+		    tocitem = (SearchTOCItem) node.getUserObject();
+		    URL testURL = tocitem.getURL();
+		    if (testURL != null && url != null && url.sameFile(testURL)) {
+			tocitem = (SearchTOCItem) node.getUserObject();
+			tocitem.addSearchHit(new SearchHit(item.getConfidence(),
+							   item.getBegin(),
+							   item.getEnd()));
+			foundNode = true;
+			break;
+		    }
+		}
+		if (!foundNode) {
+		    tocitem = new SearchTOCItem(item);
+		    node = new DefaultMutableTreeNode(tocitem);
+		    nodes.addElement(node);
+		}
+	    }
+	    reorder(nodes);
+	    ((DefaultTreeModel)tree.getModel()).reload();
+	}
+    }
+
+    public synchronized void searchStarted(SearchEvent e) {
+	debug ("search Started");
+	SwingUtilities.invokeLater(new Runnable() {
+	    public void run() {
+		TreeSelectionModel tsm = tree.getSelectionModel();
+		tsm.clearSelection();
+		topNode.removeAllChildren();
+		((DefaultTreeModel)tree.getModel()).reload(); 
+		tree.invalidate();
+		tree.repaint();
+	    }
+	});
+    }
+
+    public synchronized void searchFinished(SearchEvent e) {
+	SwingUtilities.invokeLater(new Runnable() {
+	    public void run() {
+		TreeSelectionModel tsm = tree.getSelectionModel();
+		if (lastTOCnode == null && topNode.getChildCount() > 0) {
+		    DefaultMutableTreeNode node = 
+			(DefaultMutableTreeNode) topNode.getFirstChild();
+		    if (node != null) {
+			tsm.clearSelection();
+			tsm.setSelectionPath(new TreePath(node.getPath()));
+		    }
+		} else {
+		    // beep
+		    searchnav.getToolkit().beep();
+		}
+		searchparams.setCursor(paramCursor);
+		tree.setCursor(treeCursor);
+	    }
+	});
+	return;
+    }
+					   
+
+    /**
+     * For printf debugging.
+     */
+    private static boolean debug = false;
+    private static void debug(String str) {
+        if (debug) {
+            System.out.println("BasicSearchNavigatorUI: " + str);
+        }
+    }
+}
+
+
+
diff --git a/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicTOCCellRenderer.java b/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicTOCCellRenderer.java
new file mode 100644
index 0000000000000000000000000000000000000000..1350ac713948fd9581d0122efdf5022704da3f40
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicTOCCellRenderer.java
@@ -0,0 +1,188 @@
+/*
+ * @(#)BasicTOCCellRenderer.java	1.25 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+/*
+ * @(#) BasicTOCCellRenderer.java 1.25 - last change made 10/30/06
+ */
+
+package javax.help.plaf.basic;
+
+import javax.swing.*;
+import javax.swing.tree.DefaultTreeCellRenderer;
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.TreeNode;
+import java.awt.*;
+import java.net.URL;
+import java.util.Locale;
+import javax.help.TOCItem;
+import javax.help.TOCView;
+import javax.help.Map;
+import javax.help.HelpUtilities;
+import javax.help.Map.ID;
+
+/**
+ * Basic cell renderer for TOC UI.
+ *
+ * @author Roger D. Brinkley
+ * @author Eduardo Pelegri-Llopart
+ * @version   1.25     10/30/06
+ */
+
+public class BasicTOCCellRenderer extends DefaultTreeCellRenderer
+{
+    protected Map map;
+    protected TOCView view;
+
+    public BasicTOCCellRenderer(Map map) {
+	this(map, null);
+    }
+	
+    public BasicTOCCellRenderer(Map map, TOCView view) {
+	super();
+	this.map = map;
+	this.view = view;
+    }
+
+    /**
+      * Configures the renderer based on the components passed in.
+      * Sets the value from messaging value with toString().
+      * The foreground color is set based on the selection and the icon
+      * is set based on on leaf and expanded.
+      */
+    public Component getTreeCellRendererComponent(JTree tree, Object value,
+						  boolean sel,
+						  boolean expanded,
+						  boolean leaf, int row,
+						  boolean hasFocus)
+    {
+
+        String stringValue = "";
+
+        // variable hasFocus was private to DefaultTreeCellRenderer since jdk1.3
+        try {
+            this.hasFocus = hasFocus;
+        } catch (IllegalAccessError e) {
+        }
+
+        TOCItem item
+	    = (TOCItem) ((DefaultMutableTreeNode) value).getUserObject();
+
+	if (item != null) {
+	    stringValue = item.getName();
+	}
+
+	setText(stringValue);
+	if (sel) {
+	    setForeground(getTextSelectionColor());
+	} else {
+	    setForeground(getTextNonSelectionColor());
+	}
+
+	ImageIcon icon = null;
+	if (item != null) {
+	    ID id = item.getImageID();
+	    if (id != null) {
+		try {
+		    URL url = map.getURLFromID(id);
+		    icon = new ImageIcon(url);
+		} catch (Exception e) {
+		}
+	    }
+	}
+
+	// Set the locale of this if there is a lang value
+	if (item != null) {
+	    Locale locale = item.getLocale();
+	    if (locale != null) {
+		setLocale(locale);
+	    }
+	}
+
+	// determine which icon to display
+	if (icon != null) {
+	    setIcon(icon);
+	} else if (leaf) {
+	    setIcon(getLeafIcon());
+	} else if (expanded) {
+	    setIcon(getOpenIcon());
+	} else {
+	    setIcon(getClosedIcon());
+	}
+	    
+	selected = sel;
+
+	return this;
+    }
+
+    public Icon getLeafIcon() {
+	Icon icon = null;
+	if (view != null) {
+	    ID id = view.getTopicImageID();
+	    if (id != null) {
+		try {
+		    URL url = map.getURLFromID(id);
+		    icon = new ImageIcon(url);
+		    return icon;
+		} catch (Exception e) {
+		}
+	    }
+	}
+	return super.getLeafIcon();
+    }
+
+    public Icon getOpenIcon() {
+	Icon icon = null;
+	if (view != null) {
+	    ID id = view.getCategoryOpenImageID();
+	    if (id != null) {
+		try {
+		    URL url = map.getURLFromID(id);
+		    icon = new ImageIcon(url);
+		    return icon;
+		} catch (Exception e) {
+		}
+	    }
+	}
+	return super.getOpenIcon();
+    }
+
+    public Icon getClosedIcon() {
+	Icon icon = null;
+	if (view != null) {
+	    ID id = view.getCategoryClosedImageID();
+	    if (id != null) {
+		try {
+		    URL url = map.getURLFromID(id);
+		    icon = new ImageIcon(url);
+		    return icon;
+		} catch (Exception e) {
+		}
+	    }
+	}
+	return super.getClosedIcon();
+    }
+
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicTOCNavigatorUI.java b/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicTOCNavigatorUI.java
new file mode 100644
index 0000000000000000000000000000000000000000..e57c3e91aac63fe3218d7e9f1145e44e8446219b
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/plaf/basic/BasicTOCNavigatorUI.java
@@ -0,0 +1,807 @@
+/*
+ * @(#)BasicTOCNavigatorUI.java	1.99 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+/*
+ * @(#) BasicTOCNavigatorUI.java 1.99 - last change made 10/30/06
+ */
+
+package javax.help.plaf.basic;
+
+import javax.help.*;
+import javax.help.plaf.HelpNavigatorUI;
+import javax.help.plaf.HelpUI;
+import javax.help.event.HelpModelListener;
+import javax.help.event.HelpModelEvent;
+import com.sun.java.help.impl.SwingWorker;
+import java.util.EventObject;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+import javax.swing.ImageIcon;
+import javax.swing.JComponent;
+import javax.swing.JScrollPane;
+import javax.swing.JTree;
+import javax.swing.RepaintManager;
+import javax.swing.UIManager;
+import javax.swing.SwingUtilities;
+import javax.swing.plaf.ComponentUI;
+import javax.swing.tree.*;
+import javax.swing.event.*;
+import java.awt.*;
+import java.io.Reader;
+import java.io.Serializable;
+import java.net.URL;
+import java.net.URLConnection;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.awt.event.ComponentEvent;
+import java.awt.event.ComponentListener;
+import javax.help.Map.ID;
+import java.util.Locale;
+import java.lang.reflect.Method;
+
+/**
+ * The default UI for JHelpNavigator of type TOC.
+ *
+ * @author Roger D. Brinkley
+ * @author Eduardo Pelegri-Llopart
+ * @author Stepan Marek
+ * @author Richard Gregor
+ * @version   1.99     10/30/06
+ */
+public class BasicTOCNavigatorUI extends HelpNavigatorUI
+             implements HelpModelListener, TreeSelectionListener,
+                        PropertyChangeListener, ComponentListener,
+                        Serializable
+{
+    protected JHelpTOCNavigator toc;
+    protected JScrollPane sp;
+    protected DefaultMutableTreeNode topNode;
+    protected JTree tree;
+    private boolean inInstallUI = false;
+    private SwingWorker worker = null;
+
+    public static ComponentUI createUI(JComponent x) {
+        return new BasicTOCNavigatorUI((JHelpTOCNavigator) x);
+    }
+    
+    public BasicTOCNavigatorUI(JHelpTOCNavigator b) {
+	debug (this + " " + "CreateUI - sort of");
+        ImageIcon icon = getImageIcon(b.getNavigatorView());
+        if (icon != null) {
+            setIcon(icon);
+        } else {
+	    setIcon(UIManager.getIcon("TOCNav.icon"));
+	}
+    }
+
+    public void installUI(JComponent c) {
+	debug (this + " " + "installUI");
+
+	inInstallUI = true;
+	toc = (JHelpTOCNavigator)c;
+	HelpModel model = toc.getModel();
+
+	toc.setLayout(new BorderLayout());
+	toc.addPropertyChangeListener(this);
+        toc.addComponentListener(this);
+	if (model != null) {
+	    model.addHelpModelListener(this); // for our own changes            
+	}
+
+	topNode = new DefaultMutableTreeNode();
+
+	tree = new JTree(topNode);	
+	TreeSelectionModel tsm = tree.getSelectionModel();
+        // tsm.setSelectionMode(TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION);
+	tsm.addTreeSelectionListener(this);
+        
+	tree.setShowsRootHandles(false);
+	tree.setRootVisible(false);
+
+	setCellRenderer(toc.getNavigatorView(), tree);
+
+	sp = new JScrollPane();
+	sp.getViewport().add(tree);
+        
+	toc.add("Center", sp);
+	reloadData();
+	inInstallUI = false;
+    }
+
+    /**
+     * Sets the desired cell renderer on this tree.  This is exposed for redefinition
+     * by subclases.
+     */
+    protected void setCellRenderer(NavigatorView view, JTree tree) {
+	// Use the combined map to drive the TOC tree actions
+	Map map = view.getHelpSet().getCombinedMap();
+	tree.setCellRenderer(new BasicTOCCellRenderer(map, (TOCView)view));
+    }
+
+    public void uninstallUI(JComponent c) {
+	debug (this + " " + "unistallUI");
+	HelpModel model = toc.getModel();
+
+        toc.removeComponentListener(this);
+	toc.removePropertyChangeListener(this);
+	TreeSelectionModel tsm = tree.getSelectionModel();
+	tsm.removeTreeSelectionListener(this);
+	toc.setLayout(null);
+	toc.removeAll();
+
+	if (model != null) {
+	    model.removeHelpModelListener(this);
+	}
+
+	toc = null;
+    }
+
+    public Dimension getPreferredSize(JComponent c) {
+	/*
+	if (sp != null) {
+	    return ((ScrollPaneLayout)sp.getLayout()).preferredLayoutSize(sp);
+	} else {
+	    return new Dimension(200,100);
+	}
+	*/
+	return new Dimension (200,100);
+    }
+
+    public Dimension getMinimumSize(JComponent c) {
+	return new Dimension(100,100);
+    }
+
+    public Dimension getMaximumSize(JComponent c) {
+	return new Dimension(Short.MAX_VALUE, Short.MAX_VALUE);
+    }
+
+    /**
+     * Reloads the presentation data.
+     */
+    private void reloadData() {
+	debug("reloadData");
+
+	// parse the TOC data into topNode
+	TOCView view = (TOCView) toc.getNavigatorView();
+
+	if (worker != null) {
+	    // Something is still going on. Stop it and start over
+	    worker.interrupt();
+	}
+	worker = new NavSwingWorker(view);
+	worker.start(Thread.MIN_PRIORITY);
+    }
+
+    /**
+     * load the data for the navigator. Will be run on a separate
+     * thread.
+     */
+    private synchronized Object loadData(TOCView view) {
+	if (view == null) {
+	    return Boolean.FALSE;
+	}
+
+	// remove all children
+	topNode.removeAllChildren(); 
+	    
+	String mergeType = view.getMergeType();
+	    
+	Locale locale = view.getHelpSet().getLocale();
+	    
+	DefaultMutableTreeNode node = view.getDataAsTree();
+	    
+	    // Make sure the children are all handled correctly
+	MergeHelpUtilities.mergeNodeChildren(mergeType, node);
+        
+	// This is a tricky one. As you remove the entries from one node to
+	// another the list shrinks. So you can't use an Enumated list to do
+	// the move.
+	while (node.getChildCount() > 0) {
+	    topNode.add((DefaultMutableTreeNode) node.getFirstChild());
+	}
+	    
+	// Add all of the subhelpset's data
+	addSubHelpSets(view.getHelpSet());
+	return Boolean.TRUE;
+    }
+
+
+    /*
+     * Presents the data loaded in loadData. Will be run on the
+     * Swing event thread.
+     */
+    private void presentData() {
+	// reload the tree data
+	((DefaultTreeModel)tree.getModel()).reload(); 
+	    
+	setVisibility(topNode);
+
+	    
+	if (toc.getModel() != null) {
+	    ID id = toc.getModel().getCurrentID();
+	    if (id != null) {
+		DefaultMutableTreeNode selectedNode = findID(topNode, id);
+		selectNode(selectedNode);
+	    }
+	}
+    }
+
+    private class NavSwingWorker extends SwingWorker {
+	TOCView view;
+
+	public NavSwingWorker (TOCView view) {
+	    super();
+	    this.view = view;
+	}
+
+	public Object construct() {
+	    return loadData(view);
+	}
+
+	public void finished() {
+	    if ((Boolean)get() == Boolean.TRUE) {
+		presentData();
+	    }
+	}
+    }
+
+
+    /**
+     * Reloads the presentation data using new help model. Changes the navigator if new model contains
+     * view with the same name as former view
+     **/
+    private void reloadData(HelpModel model) {
+	debug("reloadData using new model");
+        
+        TOCView view = null;          
+        
+        HelpSet newHelpSet = model.getHelpSet();
+        TOCView oldView = (TOCView) toc.getNavigatorView();
+        String oldName = oldView.getName();
+        NavigatorView[] navViews = newHelpSet.getNavigatorViews();
+        for(int i = 0 ; i < navViews.length; i++){
+            if((navViews[i].getName()).equals(oldName)){
+                NavigatorView tempView = navViews[i];
+                if(tempView instanceof TOCView){
+                    view = (TOCView) tempView;
+                    break;
+                }
+            }
+        }
+        
+	if (worker != null) {
+	    // Something is still going on. Stop it and start over
+	    worker.interrupt();
+	}
+	worker = new NavSwingWorker(view);
+	worker.start(Thread.MIN_PRIORITY);
+    }
+
+    /** Adds subhelpsets
+     *
+     * @param hs The HelpSet which subhelpsets will be added
+     */
+    protected void addSubHelpSets(HelpSet hs){
+	debug("addSubHelpSets");
+        for( Enumeration e = hs.getHelpSets(); e.hasMoreElements(); ) {
+	    HelpSet ehs = (HelpSet) e.nextElement();
+            // merge views
+            NavigatorView[] views = ehs.getNavigatorViews();
+            for(int i = 0; i < views.length; i++){
+                if(toc.canMerge(views[i]))
+                    doMerge(views[i]);
+            }
+            addSubHelpSets( ehs );
+	}
+    }
+    
+    /**
+     * Expands entry path and entry itself( when entry is not empty) for specific id
+     *
+     * @param target The target of entry
+     */
+   
+    private void expand(String target){
+        debug("expand called");
+        //find all nodes with certain id
+        Enumeration nodes = findNodes(target).elements();
+        DefaultMutableTreeNode node = null;
+        
+        while(nodes.hasMoreElements()){
+            node = (DefaultMutableTreeNode)nodes.nextElement();
+            debug("expandPath :"+node);
+            if(node.getChildCount() > 0){
+                DefaultMutableTreeNode child =(DefaultMutableTreeNode) node.getFirstChild();
+                TreePath path = new TreePath(child.getPath());
+                tree.makeVisible(path);
+            }
+            else{
+                TreeNode[] treeNode = node.getPath();
+                TreePath path = new TreePath(treeNode);
+                //tree.scrollPathToVisible(path);
+                tree.makeVisible(path);
+            }
+        }
+    }        
+    
+    /**
+     * Returns all nodes with certain id
+     *
+     * @param target The target of entry
+     *     
+     */
+    private Vector findNodes(String target){
+        Enumeration nodes = topNode.preorderEnumeration();
+        DefaultMutableTreeNode node = null;
+        Vector nodeFound = new Vector();
+        
+        while(nodes.hasMoreElements()){
+                node = (DefaultMutableTreeNode)nodes.nextElement();
+                debug(" node :"+ node.toString());
+                if(node != null){
+                    TOCItem tocItem = (TOCItem)node.getUserObject();
+                    if(tocItem == null)
+                        debug("tocItem is null");
+                    else{
+                        Map.ID id = tocItem.getID();
+                        if(id != null){
+                            debug("id name :"+id.id);
+                            debug("target :"+target);
+                            Map.ID itemID = null;
+                            try{
+                                itemID = Map.ID.create(target,toc.getModel().getHelpSet());
+                            }
+                            catch(BadIDException exp){
+                                System.err.println("Not valid ID :"+target );
+                                break;
+                            }
+                            if(id.equals(itemID))
+                                nodeFound.addElement(node);
+                        }
+                    }
+                }
+        }
+                                
+        return nodeFound;
+    }
+    
+    /**
+     * Collapses entry specified by id. If entry is empty collapses its parent.
+     *
+     * @param target The target of entry 
+     */
+      
+    private void collapse(String target){
+        Enumeration nodes = findNodes(target).elements();
+        DefaultMutableTreeNode node = null;
+        debug("collapse called");
+        
+        while(nodes.hasMoreElements()){
+            node = (DefaultMutableTreeNode)nodes.nextElement();
+            if(node.getChildCount() > 0){
+                TreeNode[] treeNode = node.getPath();
+                TreePath path = new TreePath(treeNode);
+                tree.collapsePath(path);
+                tree.collapseRow(tree.getRowForPath(path));
+            }
+            else{
+                DefaultMutableTreeNode parent =(DefaultMutableTreeNode) node.getParent();
+                TreePath path = new TreePath(parent.getPath());
+                tree.collapseRow(tree.getRowForPath(path));
+            }
+        }
+    }
+    
+
+    /**
+     * Merges in the navigational data from another IndexView.
+     */
+
+    public void doMerge(NavigatorView view) {
+	debug("merging data");
+       
+        Merge mergeObject = Merge.DefaultMergeFactory.getMerge(toc.getNavigatorView(),view);
+        if(mergeObject != null) {
+            mergeObject.processMerge(topNode);
+	}
+        
+    }
+
+    /**
+     * Merges in the navigational data from another TOCView.
+     *
+     * @param view A TOCView.  Note the actual argument is of a NavigatorView type
+     * so it replaces the correct NavigatorUI method.
+     */
+
+    public void merge(NavigatorView view) {
+	debug("merging "+view);
+        doMerge(view);
+
+        //reload the tree data
+	((DefaultTreeModel)tree.getModel()).reload(); 
+	setVisibility(topNode);
+    }
+
+    /**
+     * Removes the navigational data.
+     *
+     * @param view A TOCView.  Note the actual argument is of a NavigatorView type
+     * so it replaces the correct NavigatorUI method.
+     */
+
+    public void remove(NavigatorView view) {
+	debug("removing "+view);
+
+	remove(topNode, view.getHelpSet());
+	
+	// reload the tree data
+	((DefaultTreeModel)tree.getModel()).reload(); 
+	setVisibility(topNode);
+    }
+
+    /**
+     * Recursively removes all children of the node that have either hs or a HelpSet that
+     * is included in hs as their HelpSet data.
+     *
+     * Recursion is stopped when a node is removed.  This is because of the
+     * property of the merge mechanism.
+     *
+     * @param node The node from where to remove its children
+     * @param hs The non-null helpset to use
+     */
+
+    private void remove(DefaultMutableTreeNode node,
+			HelpSet hs) {
+	debug("remove("+node+", "+hs+")");
+
+	// a simple node.children() does not work because the
+	// enumeration is voided when a child is removed
+
+	// getNextSibling() has a linear search, so we won't do that either
+
+	// Collect all to be removed
+	Vector toRemove = new Vector();
+	
+	for (Enumeration e = node.children();
+	     e.hasMoreElements(); ) {
+	    DefaultMutableTreeNode child
+		= (DefaultMutableTreeNode) e.nextElement();
+	    debug("  considering "+child);
+	    TOCItem item = (TOCItem) child.getUserObject();
+	    HelpSet chs = item.getHelpSet();
+	    debug ("chs=" + chs + " hs.contains(chs)=" + hs.contains(chs));
+	    if (chs != null &&
+		hs.contains(chs)) {
+		if (child.isLeaf()) {
+		    // if the child has no children then just remove it
+		    debug("  tagging for removal: "+child);
+		    toRemove.addElement(child); // tag to be removed...
+		} else {
+		    // be carefull here. While the child hs is one to be
+		    // removed it is possible that there are children that
+		    // are not of this hs. Attempt to remove the 
+		    // child's children first. If they're are any children left
+		    // the change the hs to be the hs of the first child
+		    remove(child, hs);
+		    if (child.isLeaf()) {
+			// no more children remove the child as well
+			debug("  tagging for removal: "+child);
+			toRemove.addElement(child); // tag to be removed...
+		    } else {
+			// nuts! There are children from different hs
+			// change the hs of the TOCItem to be the hs of the
+			// first child
+			DefaultMutableTreeNode childOne = 
+			    (DefaultMutableTreeNode) child.getFirstChild();
+			TOCItem itemOne =  (TOCItem) childOne.getUserObject();
+			item.setHelpSet(itemOne.getHelpSet());
+			debug("  orphaned children - changing hs: "+child);
+		    }
+		}
+	    } else {
+		// the child doesn't need to be removed but possibly it's
+		// children will
+		remove(child, hs);
+	    }
+	}
+	    
+	// Now remove them
+	for (int i=0; i<toRemove.size(); i++) {
+	    debug("  removing "+toRemove.elementAt(i));
+	    node.remove((DefaultMutableTreeNode) toRemove.elementAt(i));
+	}
+    }
+
+
+    // In the TOC only set the visibility at the next to the top node
+    // unless the node is set for expansion. Always expand the first row
+    private void setVisibility (DefaultMutableTreeNode node) {
+	TOCItem item = (TOCItem)node.getUserObject();
+	int expandType = TreeItem.DEFAULT_EXPANSION;
+	if (item != null) {
+	    expandType = item.getExpansionType();
+	}
+	TreePath path = new TreePath(node.getPath());
+	int pathcount = path.getPathCount();
+	if (node == topNode || 
+	    (pathcount <= 2 && expandType == TreeItem.DEFAULT_EXPANSION) ||
+	    (expandType == TreeItem.EXPAND)) {
+	    tree.expandPath(new TreePath(node.getPath()));
+	    if (! node.isLeaf()) {
+		int max = node.getChildCount();
+		for (int i=0; i<max; i++) {
+		    setVisibility((DefaultMutableTreeNode)node.getChildAt(i));
+		}
+	    }
+	}
+    }
+
+    /**
+     * Processes an idChanged event.
+     */
+
+    public synchronized void idChanged(HelpModelEvent e) {
+ 	ID id = e.getID();
+	HelpModel helpModel = toc.getModel();
+	debug("idChanged("+e+")");
+
+	if (e.getSource() != helpModel) {
+	    debug("Internal inconsistency!");
+	    debug("  "+e.getSource()+" != "+helpModel);
+	    throw new Error("Internal error");
+	}
+
+	if (id == null) {
+	    id = helpModel.getHelpSet().getCombinedMap().getClosestID(e.getURL());
+	}
+	TreePath s = tree.getSelectionPath();
+	if (s != null) {
+	    Object o = s.getLastPathComponent();
+	    // should require only a TreeNode
+	    if (o instanceof DefaultMutableTreeNode) {
+		DefaultMutableTreeNode tn = (DefaultMutableTreeNode) o;
+		TOCItem item = (TOCItem) tn.getUserObject();
+		if (item != null) {
+		    ID nId = item.getID();
+		    if (nId != null && nId.equals(id)) {
+			return;
+		    }
+		}
+	    }
+	}
+
+	DefaultMutableTreeNode node = findID(topNode, id);
+	selectNode(node);
+    }
+
+    // Note - this recursive implementation may need tuning for very large TOC - epll
+
+    private DefaultMutableTreeNode findID(DefaultMutableTreeNode node, ID id) {
+	debug("findID: ("+id+")");
+	debug("  node: "+node);
+
+	// check on the ID
+	if (id == null) {
+	    return null;
+	}
+	TOCItem item = (TOCItem) node.getUserObject();
+	if (item != null) {
+	    ID testID = item.getID();
+	    debug("  testID: "+testID);
+	    if (testID != null && testID.equals(id)) {
+		return node;
+	    }
+	}
+	int size = node.getChildCount();
+	for (int i=0; i<size ; i++) {
+ 	    DefaultMutableTreeNode tmp = 
+		(DefaultMutableTreeNode) node.getChildAt(i);
+	    DefaultMutableTreeNode test = findID(tmp, id);
+	    if (test != null) {
+		return test;
+	    }
+	}
+	return null;
+    }
+
+    /**
+     * Select a certian node
+     */
+    private void selectNode(DefaultMutableTreeNode node) {
+	if (node == null) {
+	    // node doesn't exist. Need to clear the selection.
+	    tree.clearSelection();
+	    return;
+	}
+	TreePath path = new TreePath(node.getPath());
+	tree.expandPath(path);
+	tree.setSelectionPath(path);
+	tree.scrollPathToVisible(path);
+    }
+
+    protected JHelpNavigator getHelpNavigator() {
+        return toc;
+    }
+
+    public void valueChanged(TreeSelectionEvent e) {
+
+        JHelpNavigator navigator = getHelpNavigator();
+        HelpModel helpmodel = navigator.getModel();
+
+        debug("ValueChanged: "+e);
+	debug("  model: "+helpmodel);
+
+        // send selected items into navigator
+        TreeItem[] items = null;
+        TreePath[] paths = tree.getSelectionPaths();
+        if (paths != null) {
+            items = new TreeItem[paths.length];
+            for (int i = 0; i < paths.length; i++) {
+                if (paths[i] != null) {
+                    DefaultMutableTreeNode node = (DefaultMutableTreeNode) paths[i].getLastPathComponent();
+                    items[i] = (TreeItem) node.getUserObject();
+                }
+            }
+        }
+        navigator.setSelectedItems(items);
+
+        // change current id only if one items is selected
+        if (items != null && items.length == 1) {
+            TOCItem item = (TOCItem) items[0];
+            if (item != null && item.getID() != null) {
+		String presentation = item.getPresentation();
+		if (presentation == null) {
+		    // This is the old way of doing things 
+		    // set the currentID in the helpModel
+		    try {
+			helpmodel.setCurrentID(item.getID(), item.getName(), navigator);
+		    } catch (InvalidHelpSetContextException ex) {
+			System.err.println("BadID: "+item.getID());
+			return;
+		    }
+		} else {
+		    // Tricky situation here
+		    // Don't select a Tree item if we're installing
+		    // and that TreeItem displays in different presentation
+		    // This can lead to infinate loops
+		    if (inInstallUI) {
+			tree.clearSelection();
+			return;
+		    }
+
+		    // using a Presentation
+		    // Get a Presentation
+		    Presentation pres;
+		    HelpSet hs = helpmodel.getHelpSet();
+		    ClassLoader loader;
+		    Class klass;
+		    Class types[] = { HelpSet.class,
+				      String.class};
+		    Object args[] = { hs,
+				      item.getPresentationName()};		
+		    try {
+			loader = hs.getLoader();
+			if (loader == null) {
+			    klass = Class.forName(presentation);
+			} else {
+			    klass = loader.loadClass(presentation);
+			}
+			Method m = klass.getMethod("getPresentation", types);
+			pres = (Presentation)m.invoke(null, args);
+		    } catch (Exception ex) {
+			throw new RuntimeException("error invoking presentation" );
+		    }
+
+		    if (pres == null) {
+			return;
+		    }
+
+		    // Minor adjustments for Windows and Popups
+		    if (pres instanceof WindowPresentation) {
+			((WindowPresentation)pres).setActivationObject(tree);
+		    }
+		    if (pres instanceof Popup) {
+			((Popup)pres).setInvokerInternalBounds(tree.getPathBounds(paths[0]));
+			((Popup)pres).setInvoker((Component)tree);
+		    }
+
+		    // set the id to be displayed
+		    try {
+			pres.setCurrentID(item.getID());
+		    } catch (InvalidHelpSetContextException ex) {
+			System.err.println("BadID: "+item.getID());
+			return;
+		    }
+
+		    // diplay the presentation
+		    pres.setDisplayed(true);
+		}
+            }
+        }
+    }
+
+    public void propertyChange(PropertyChangeEvent event) {
+	debug(this + " " + "propertyChange: " + event.getSource() + " "  +
+	      event.getPropertyName());
+
+	if (event.getSource() == toc) {
+	    String changeName = event.getPropertyName();
+	    if (changeName.equals("helpModel")) {
+                reloadData((HelpModel)event.getNewValue());             
+      	    } else  if (changeName.equals("font")) {
+		debug ("Font change");
+		Font newFont = (Font)event.getNewValue();
+		tree.setFont(newFont);
+		RepaintManager.currentManager(tree).markCompletelyDirty(tree);
+            } else if(changeName.equals("expand")){
+                debug("Expand change");
+                expand((String)event.getNewValue());
+            } else if(changeName.equals("collapse")){
+                debug("Collapse change");
+                collapse((String)event.getNewValue());
+            }
+	    // changes to UI property?
+	}
+        
+    }
+
+    /**
+     * Invoked when the component's size changes.
+     */
+    public void componentResized(ComponentEvent e) {
+    }
+    
+    /**
+     * Invoked when the component's position changes.
+     */
+    public void componentMoved(ComponentEvent e) {
+    }
+    
+    /**
+     * Invoked when the component has been made visible.
+     */
+    public void componentShown(ComponentEvent e) {
+        tree.requestFocus();
+    }
+    
+    /**
+     * Invoked when the component has been made invisible.
+     */
+    public void componentHidden(ComponentEvent e) {
+    }
+    
+    /**
+     * For printf debugging.
+     */
+    protected static final boolean debug = false;
+    protected static void debug(String str) {
+        if (debug) {
+            System.out.println("BasicTOCNavigatorUI: " + str);
+        }
+    }
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/plaf/gtk/GTKCursorFactory.java b/jhMaster/JavaHelp/src/new/javax/help/plaf/gtk/GTKCursorFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..9d2397eea3b79f2598e44b683fd48e63eb812256
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/plaf/gtk/GTKCursorFactory.java
@@ -0,0 +1,195 @@
+/*
+ * @(#)GTKCursorFactory.java	1.2 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help.plaf.gtk;
+
+import java.io.*;
+import javax.swing.ImageIcon;
+import java.awt.Cursor;
+import java.awt.Dimension;
+import java.awt.Image;
+import java.awt.Point;
+import java.awt.Toolkit;
+import java.awt.image.BufferedImage;
+import java.util.ResourceBundle;
+import java.util.MissingResourceException;
+import java.util.PropertyResourceBundle;
+
+/**
+ * Factory object that can vend cursors appropriate for the GTK L & F.
+ * <p>
+ *
+ * @version 1.2	10/30/06
+ * @author Roger D. Brinkley
+ */
+public class GTKCursorFactory {
+    private static Cursor onItemCursor;
+    private static Cursor dndCursor;
+    private static GTKCursorFactory theFactory;
+
+    /**
+     * Returns the OnItem cursor.
+     */
+    public static Cursor getOnItemCursor() {
+	debug ("getOnItemCursor");
+	if (theFactory == null) {
+	    theFactory = new GTKCursorFactory();
+	}
+	if (onItemCursor == null) {
+	    onItemCursor = theFactory.createCursor("OnItemCursor");
+	}
+	return onItemCursor;
+    }
+
+    /**
+     * Returns the DnDCursor.
+     */
+    public static Cursor getDnDCursor(){
+        debug("getDnDCursor");
+        if (theFactory == null) {
+	    theFactory = new GTKCursorFactory();
+	}
+	if (dndCursor == null) {
+	    dndCursor = theFactory.createCursor("DnDCursor");
+	}
+	return dndCursor;
+    }
+    
+    private Cursor createCursor(String name) {
+ 	String gifFile = null;
+	String hotspot = null;
+	ImageIcon icon;
+	Point point;
+
+	debug("CreateCursor for " + name);
+
+	// Get the Property file
+	InputStream is = getClass().getResourceAsStream("images/" + name + ".properties");
+	if (is == null) {
+	    debug(getClass().getName() + "/" + 
+			       "images/" + name + ".properties" + " not found.");
+	    return null;
+	}
+	try {
+	    ResourceBundle resource = new PropertyResourceBundle(is);
+	    gifFile = resource.getString("Cursor.File");
+	    hotspot = resource.getString("Cursor.HotSpot");
+	} catch (MissingResourceException e) {
+	    debug(getClass().getName() + "/" + 
+			       "images/" + name + ".properties" + " invalid.");
+	    return null;
+	} catch (IOException e2) {
+	    debug(getClass().getName() + "/" + 
+			       "images/" + name + ".properties" + " invalid.");
+	    return null;
+	}
+
+	// Create the icon
+	byte[] buffer = null;
+	try {
+	    /* Copies resource into a byte array.  This is
+	     * necessary because several browsers consider
+	     * Class.getResource a security risk because it
+	     * can be used to load additional classes.
+	     * Class.getResourceAsStream returns raw
+	     * bytes, which JH can convert to an image.
+	     */
+	    InputStream resource = 
+		getClass().getResourceAsStream(gifFile);
+	    if (resource == null) {
+		debug(getClass().getName() + "/" + 
+				   gifFile + " not found.");
+		return null; 
+	    }
+	    BufferedInputStream in = 
+		new BufferedInputStream(resource);
+	    ByteArrayOutputStream out = 
+		new ByteArrayOutputStream(1024);
+	    buffer = new byte[1024];
+	    int n;
+	    while ((n = in.read(buffer)) > 0) {
+		out.write(buffer, 0, n);
+	    }
+	    in.close();
+	    out.flush();
+	    
+	    buffer = out.toByteArray();
+	    if (buffer.length == 0) {
+		debug("warning: " + gifFile + 
+				   " is zero-length");
+		return null;
+	    }
+	} catch (IOException ioe) {
+	    debug(ioe.toString());
+	    return null;
+	}
+
+	icon = new ImageIcon(buffer);
+
+	// create the point
+	int k = hotspot.indexOf(',');
+	point = new Point(Integer.parseInt(hotspot.substring(0,k)),
+			  Integer.parseInt(hotspot.substring(k+1)));
+	
+	debug ("Toolkit fetching cursor");
+	try {
+            
+            Image image = icon.getImage();
+            int width = icon.getIconWidth();
+            int height = icon.getIconHeight();
+            
+            Toolkit toolkit = Toolkit.getDefaultToolkit();
+            Dimension d = toolkit.getBestCursorSize(width, height);
+
+            if ((d.width > width) || (d.height > height)) {
+                try {
+                    Image bimage = new BufferedImage(d.width, d.height, BufferedImage.TYPE_INT_ARGB);
+                    bimage.getGraphics().drawImage(icon.getImage(), 0, 0, icon.getImageObserver());
+                    image = bimage;
+                } catch (Exception ex) {
+                }
+            }
+            
+	    return toolkit.createCustomCursor(image, point, name);
+            
+	} catch (NoSuchMethodError err) {
+	    //	    return Cursor.getPredefinedCursor(Cursor.HAND_CURSOR);
+	    return null;
+	}
+    }
+
+    /**
+     * For printf debugging.
+     */
+    private static final boolean debug = false;
+    private static void debug(String str) {
+        if (debug) {
+            System.out.println("GTKCursorFactory: " + str);
+        }
+    }
+
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/plaf/package.html b/jhMaster/JavaHelp/src/new/javax/help/plaf/package.html
new file mode 100644
index 0000000000000000000000000000000000000000..060ede57db8cad7b7196e6e874caa42a38c93202
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/plaf/package.html
@@ -0,0 +1,54 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<!--
+
+  @(#)package.html	1.2 99/03/19
+
+  Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+  DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+  This code is free software; you can redistribute it and/or modify it
+  under the terms of the GNU General Public License version 2 only, as
+  published by the Free Software Foundation.  Sun designates this
+  particular file as subject to the "Classpath" exception as provided
+  by Sun in the LICENSE file that accompanied this code.
+
+  This code is distributed in the hope that it will be useful, but WITHOUT
+  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+  version 2 for more details (a copy is included in the LICENSE file that
+  accompanied this code).
+
+  You should have received a copy of the GNU General Public License version
+  2 along with this work; if not, write to the Free Software Foundation,
+  Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+  Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+  CA 95054 USA or visit www.sun.com if you need additional information or
+  have any questions.
+
+-->
+
+</head>
+<body bgcolor="white">
+
+Supports access to Component UI classes.  <code>HelpUI</code> is for
+the JHelp component, <code>HelpContentViewerUI</code> is for the
+JHelpContentViewer component, and <code>HelpNavigatorUI</code> is for
+the JHelp components.
+
+<!--
+<H2>Package Specification</H2>
+Link to updated API specification to be added here.
+-->
+
+<H2>Related Documentation</H2>
+
+<P>
+For overviews, tutorials, examples, guides, tool support,
+and other documentation,
+please see the <em>JavaHelp System User's Guide</em>.
+
+  </body>
+</html>
diff --git a/jhMaster/JavaHelp/src/new/javax/help/resources/Constants.java b/jhMaster/JavaHelp/src/new/javax/help/resources/Constants.java
new file mode 100644
index 0000000000000000000000000000000000000000..c0c9f28e6dfdd49723ab3ce7958122143fb39262
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/resources/Constants.java
@@ -0,0 +1,149 @@
+/*
+ * @(#)Constants.java	1.22 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+/*
+ * @(#) Constants.java 1.22 - last change made 10/30/06
+ */
+
+package javax.help.resources;
+
+import java.util.ListResourceBundle;
+
+/**
+ * Constants used for localizing JavaHelp.
+ *
+ * These are in the form of key, value.
+ * Translators take care to only translate the values.
+ */
+
+public class Constants extends ListResourceBundle {
+    /**
+     * Overrides ListResourceBundle.
+     */
+    public Object[][] getContents() {
+        return new Object[][] {
+
+	    //  Constant strings and patterns
+	    { "helpset.wrongPublicID",
+		  "Unknown PublicID {0}"},
+	    { "helpset.wrongTitle",
+		  "Attempting to set title to {0} but already has value {1}."},
+	    { "helpset.wrongHomeID",
+		  "Attempting to set homeID to {0} but already has value {1}."},
+	    { "helpset.subHelpSetTrouble",
+		  "Trouble creating subhelpset: {0}."},
+	    { "helpset.malformedURL",
+		  "Malformed URL: {0}."},
+	    { "helpset.incorrectURL",
+		  "Incorrect URL: {0}."},
+	    { "helpset.wrongText",
+		  "{0} cannot contain text {1}."},
+	    { "helpset.wrongTopLevel",
+		  "{0} cannot be a top level tag."},
+	    { "helpset.wrongParent",
+		  "The parent tag for {0} cannot be {1}."},
+	    { "helpset.unbalanced",
+		  "Unbalanced tag {0}."},
+	    { "helpset.wrongLocale",
+		  "Warning: xml:lang attribute {0} conflicts with default {1} and with default {2}"},
+	    { "helpset.unknownVersion",
+		  "Unknown Version {0}."},
+
+		// IndexView messages
+	    { "index.invalidIndexFormat",
+		  "Warning: Invalid Index format"},
+	    { "index.unknownVersion",
+		  "Unknown Version {0}."},
+
+		// TOCView messages
+	    { "toc.wrongPublicID",
+		  "Unknown PublicID {0}"},
+	    { "toc.invalidTOCFormat",
+		  "Warning: Invalid TOC format"},
+	    { "toc.unknownVersion",
+		  "Unknown Version {0}."},
+                  
+            // FavoritesView messages
+	    { "favorites.invalidFavoritesFormat",
+		  "Warning: Invalid Favorites format"},
+	    { "favorites.unknownVersion",
+		  "Unknown Version {0}."},
+
+		// Map messages
+	    { "map.wrongPublicID",
+		  "Unknown PublicID {0}"},
+	    { "map.invalidMapFormat",
+		  "Warning: Invalid Map format"},
+	    { "map.unknownVersion",
+		  "Unknown Version {0}."},
+
+	    // GUI components
+	    // Labels
+	    { "index.findLabel", "Find: "},
+            
+	    { "search.findLabel", "Find: "},
+	    { "search.hitDesc", "Number of occurances in document"},
+	    { "search.qualityDesc", "Lowest penality value in document" },
+	    { "search.high", "High"},
+	    { "search.midhigh", "Medium high"},
+	    { "search.mid", "Medium"},
+	    { "search.midlow", "Medium low"},
+	    { "search.low", "Low"},
+            
+            { "favorites.add", "Add"},
+            { "favorites.remove", "Remove"},
+            { "favorites.folder", "New Folder"},
+            { "favorites.name", "Name"},
+            { "favorites.cut", "Cut"},
+            { "favorites.paste", "Paste"},
+            { "favorites.copy" , "Copy"},
+
+            { "history.homePage", "Home page"},
+            { "history.unknownTitle", "<unknown page title>"},
+
+            // ToolTips for Actions
+            { "tooltip.BackAction", "Previous Page"},
+	    { "tooltip.ForwardAction", "Next Page"},
+	    { "tooltip.PrintAction", "Print"},
+	    { "tooltip.PrintSetupAction", "Page Setup"},
+	    { "tooltip.ReloadAction", "Reload"},
+            { "tooltip.FavoritesAction", "Add to Favorites"},
+            { "tooltip.HomeAction", "Go to home page"},
+
+	    // Accessibility names
+	    { "access.BackAction", "Previous Button"},
+	    { "access.ForwardAction", "Next Button"},
+	    { "access.HistoryAction", "History Button"},
+	    { "access.PrintAction", "Print Button"},
+	    { "access.PrintSetupAction", "Page Setup Button"},
+	    { "access.ReloadAction", "Reload Button"},
+            { "access.HomeAction", "Home Button"},
+            { "access.FavoritesAction", "Add to Favorites Button"},
+            { "access.contentViewer", "Content Viewer"}
+
+       };
+    }
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/resources/Constants_ar.java b/jhMaster/JavaHelp/src/new/javax/help/resources/Constants_ar.java
new file mode 100644
index 0000000000000000000000000000000000000000..b61be368ded1a5d66e2633b2c559d6323277b9e1
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/resources/Constants_ar.java
@@ -0,0 +1,149 @@
+/*
+ * @(#)Constants_ar.java	1.2 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+/*
+ * @(#) Constants_ar.java 1.19 - last change made 10/19/01
+ */
+
+package javax.help.resources;
+
+import java.util.ListResourceBundle;
+
+/**
+ * Constants used for localizing JavaHelp.
+ *
+ * These are in the form of key, value.
+ * Translators take care to only translate the values.
+ */
+
+public class Constants_ar extends ListResourceBundle {
+    /**
+     * Overrides ListResourceBundle.
+     */
+    public Object[][] getContents() {
+        return new Object[][] {
+
+	    //  Constant strings and patterns
+	    { "helpset.wrongPublicID",
+		  "PublicID {0}  \u0645\u062c\u0647\u0648\u0644"},
+	    { "helpset.wrongTitle",
+		  "\u0645\u062d\u0627\u0648\u0644\u0629 \u0627\u0639\u0637\u0627\u0621 \u0639\u0646\u0648\u0627\u0646 \u0644 {0} \u0644\u0643\u0646 \u0647\u0646\u0627\u0643 \u0639\u0646\u0648\u0627\u0646 {1}."},
+	    { "helpset.wrongHomeID",
+		  ".homeID \u0642\u064a\u0645\u0629{\u0660}  \u0644 {\u0660}  \u0645\u062d\u0627\u0648\u0644\u0629 \u0627\u0639\u0637\u0627\u0621 \u0644\u0643\u0646 \u0647\u0646\u0627\u0643"},
+	    { "helpset.subHelpSetTrouble",
+		  "\u0647\u0646\u0627\u0643 \u0645\u0634\u0643\u0644\u0629 \u0627\u0646\u0634\u0627\u0621 subhelpset:{0}."},
+	    { "helpset.malformedURL",
+		  "\u0645\u0648\u0642\u0639 URL {0). \u063a\u064a\u0631 \u0635\u0627\u0644\u062d"},
+	    { "helpset.incorrectURL",
+		  "\u0645\u0648\u0642\u0639 URL {0). \u063a\u064a\u0631 \u0635\u062d\u064a\u062d"},
+	    { "helpset.wrongText",
+		  "{0} \u064a\u062a\u0639\u0630\u0631 \u0627\u062f\u062e\u0627\u0644 \u0646\u0635\u0648\u0635 {1}."},
+	    { "helpset.wrongTopLevel",
+		  "{0} TAG \u0645\u0646 \u0627\u0644\u0645\u0633\u062a\u0648\u0649 \u0627\u0644\u0623\u0639\u0644\u0649 \u063a\u064a\u0631 \u0645\u0645\u0643\u0646."},
+	    { "helpset.wrongParent",
+		  "TAG \u0631\u0626\u064a\u0633\u064a \u0645\u0646 {0} \u0644\u0627 \u064a\u0645\u0643\u0646 \u0623\u0646 \u064a\u0643\u0648\u0646 . {1}."},
+	    { "helpset.unbalanced",
+		  "tag {0} \u063a\u064a\u0631 \u0645\u0648\u0632\u0648\u0646"},
+	    { "helpset.wrongLocale",
+		  "\u062a\u0646\u0628\u064a\u0647: \u0633\u0645\u0629 xml:lang {0} \u062a\u062a\u0639\u0627\u0631\u0636 \u0645\u0639 \u0627\u0644\u0642\u064a\u0645\u0629 \u0627\u0644\u0627\u0641\u062a\u0631\u0627\u0636\u064a\u0629 {1} \u0648\u0645\u0639 \u0627\u0644\u0642\u064a\u0645\u0629 \u0627\u0644\u0627\u0641\u062a\u0631\u0627\u0636\u064a\u0629 {2}."},
+	    { "helpset.unknownVersion",
+		  "\u0627\u0635\u062f\u0627\u0631 \u0645\u062c\u0647\u0648\u0644{0}."},
+
+		// IndexView messages
+	    { "index.invalidIndexFormat",
+		  "\u062a\u0646\u0628\u064a\u0647: \u062a\u0646\u0633\u064a\u0642 \u0627\u0644\u0641\u0647\u0631\u0633 \u063a\u064a\u0631 \u0635\u0627\u0644\u062d"},
+	    { "index.unknownVersion",
+		  "\u0627\u0635\u062f\u0627\u0631 \u0645\u062c\u0647\u0648\u0644{0}."},
+
+		// TOCView messages
+	    { "toc.wrongPublicID",
+		  "PublicID {0}  \u0645\u062c\u0647\u0648\u0644"},
+	    { "toc.invalidTOCFormat",
+		  "\u062a\u0646\u0628\u064a\u0647: \u0642\u0627\u0626\u0645\u0629 \u0627\u0644\u0645\u062d\u062a\u0648\u064a\u0627\u062a \u063a\u064a\u0631 \u0635\u0627\u0644\u062d\u0629"},
+	    { "toc.unknownVersion",
+		  "\u0627\u0635\u062f\u0627\u0631 \u0645\u062c\u0647\u0648\u0644{0}."},
+                  
+            // FavoritesView messages
+	    { "favorites.invalidFavoritesFormat",
+		  "\u062a\u0646\u0628\u064a\u0647: \u062a\u0646\u0633\u064a\u0642 \u0627\u0644\u0645\u0641\u0636\u0644\u0629 \u063a\u064a\u0631 \u0635\u0627\u0644\u062d"},
+	    { "favorites.unknownVersion",
+		  "\u0627\u0635\u062f\u0627\u0631 \u0645\u062c\u0647\u0648\u0644{0}."},
+
+		// Map messages
+	    { "map.wrongPublicID",
+		  "PublicID {0}  \u0645\u062c\u0647\u0648\u0644"},
+	    { "map.invalidMapFormat",
+		  "\u062a\u0646\u0628\u064a\u0647: \u062a\u0646\u0633\u064a\u0642 \u0627\u0644 Map \u063a\u064a\u0631 \u0635\u0627\u0644\u062d"},
+	    { "map.unknownVersion",
+		  "\u0627\u0635\u062f\u0627\u0631 \u0645\u062c\u0647\u0648\u0644{0}."},
+
+	    // GUI components
+	    // Labels
+	    { "index.findLabel", "\u0628\u062d\u062b: "},
+            
+	    { "search.findLabel", "\u0628\u062d\u062b: "},
+	    { "search.hitDesc", "\u0639\u062f\u062f \u0645\u0631\u0627\u062a \u0627\u0644\u0638\u0647\u0648\u0631 \u0641\u064a \u0627\u0644\u0645\u0633\u062a\u0646\u062f"},
+	    { "search.qualityDesc", "" },
+	    { "search.high", "\u0639\u0627\u0644\u064a"},
+	    { "search.midhigh", "\u0648\u0633\u0637 \u0627\u0644\u0639\u0627\u0644\u064a"},
+	    { "search.mid", "\u0648\u0633\u0637"},
+	    { "search.midlow", "\u0648\u0633\u0637 \u0627\u0644\u0645\u0646\u062e\u0641\u0636"},
+	    { "search.low", "\u0645\u0646\u062e\u0641\u0636"},
+            
+            { "favorites.add", "\u0627\u0636\u0627\u0641\u0629"},
+            { "favorites.remove", "\u0627\u0632\u0627\u0644\u0629"},
+            { "favorites.folder", "\u0645\u062c\u0644\u062f \u062c\u062f\u064a\u062f"},
+            { "favorites.name", "\u0627\u0633\u0645"},
+            { "favorites.cut", "\u0642\u0635"},
+            { "favorites.paste", "\u0644\u0635\u0642"},
+            { "favorites.copy" , "\u0646\u0633\u062e"},
+
+            { "history.homePage", "\u0627\u0644\u0635\u0641\u062d\u0629 \u0627\u0644\u0631\u0626\u064a\u0633\u064a\u0629"},
+            { "history.unknownTitle", "<\u0639\u0646\u0648\u0627\u0646 \u0635\u0641\u062d\u0629 \u0645\u062c\u0647\u0648\u0644>"},
+
+            // ToolTips for Actions
+            { "tooltip.BackAction", "\u0627\u0644\u0635\u0641\u062d\u0629 \u0627\u0644\u0633\u0627\u0628\u0642\u0629"},
+	    { "tooltip.ForwardAction", "\u0627\u0644\u0635\u0641\u062d\u0629 \u0627\u0644\u062a\u0627\u0644\u064a\u0629"},
+	    { "tooltip.PrintAction", "\u0637\u0628\u0627\u0639\u0629"},
+	    { "tooltip.PrintSetupAction", "\u0627\u0639\u062f\u0627\u062f \u0627\u0644\u0635\u0641\u062d\u0629"},
+	    { "tooltip.ReloadAction", "\u0627\u0639\u0627\u062f\u0629 \u062a\u062d\u0645\u064a\u0644"},
+            { "tooltip.FavoritesAction", "\u0623\u0636\u0641 \u0644\u0644\u0645\u0641\u0636\u0644\u0629"},
+            { "tooltip.HomeAction", "\u0631\u062c\u0648\u0639 \u0644\u0644\u0635\u0641\u062d\u0629 \u0627\u0644\u0631\u0626\u064a\u0633\u064a\u0629"},
+
+	    // Accessibility names
+	    { "access.BackAction", "\u0627\u0644\u0632\u0631 \u0633\u0627\u0628\u0642"},
+	    { "access.ForwardAction", "\u0627\u0644\u0632\u0631 \u0627\u0644\u0627\u062a\u064a"},
+	    { "access.HistoryAction", "\u0627\u0644\u0632\u0631 \u0645\u062d\u0641\u0648\u0638\u0627\u062a"},
+	    { "access.PrintAction", "\u0627\u0644\u0632\u0631 \u0637\u0628\u0627\u0639\u0629"},
+	    { "access.PrintSetupAction", "\u0627\u0644\u0632\u0631 \u0627\u0639\u062f\u0627\u062f \u0627\u0644\u0635\u0641\u062d\u0629"},
+	    { "access.ReloadAction", "\u0627\u0644\u0632\u0631 \u0627\u0639\u0627\u062f\u0629 \u062a\u062d\u0645\u064a\u0644"},
+            { "access.HomeAction", "\u0627\u0644\u0632\u0631 \u0628\u062f\u0627\u064a\u0629"},
+            { "access.FavoritesAction", "\u0627\u0644\u0632\u0631 \u0623\u0636\u0641 \u0644\u0644\u0645\u0641\u0636\u0644\u0629"},
+            { "access.contentViewer", "\u0639\u0627\u0631\u0636 \u0627\u0644\u0645\u062d\u062a\u0648\u064a\u0627\u062a"}
+
+       };
+    }
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/resources/Constants_cs.java b/jhMaster/JavaHelp/src/new/javax/help/resources/Constants_cs.java
new file mode 100644
index 0000000000000000000000000000000000000000..7638eb43e90d23e34d89dcc2d74f75fe2d11f5ab
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/resources/Constants_cs.java
@@ -0,0 +1,149 @@
+/*
+ * @(#)Constants_cs.java	1.9 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help.resources;
+
+import java.util.ListResourceBundle;
+
+/**
+ * Constants used for localizing JavaHelp.
+ *
+ * These are in the form of key, value.
+ * Translators take care to only translate the values.
+ *
+ * @author Stepan Marek
+ * @version	1.9	10/30/06
+ *
+ */
+ 
+public class Constants_cs extends ListResourceBundle {
+    /**
+     * Overrides ListResourceBundle.
+     */
+    public Object[][] getContents() {
+        return new Object[][] {
+
+	    //  Constant strings and patterns
+	    { "helpset.wrongPublicID",
+		  "Nezn\u00e1m\u00e9 PublicID {0}"},
+	    { "helpset.wrongTitle",
+		  "Zkou\u0161\u00edm nastavit nadpis na {0}, ale nadpis m\u00e1 ji\u017e hodnotu {1}."},
+	    { "helpset.wrongHomeID",
+		  "Zkou\u0161\u00edm nastavit homeID na {0}, ale homeID ma ji\u017e hodnotu {1}."},
+	    { "helpset.subHelpSetTrouble",
+		  "Nelze vytvo\u0159it subhelpset: {0}"},
+	    { "helpset.malformedURL",
+		  "Chybn\u00fd form\u00e1t URL: {0}"},
+	    { "helpset.incorrectURL",
+		  "Chybn\u00e9 URL: {0}"},
+	    { "helpset.wrongText",
+		  "{0} nem\u016f\u017ee obsahovat text {1}."},
+	    { "helpset.wrongTopLevel",
+		  "{0} nem\u016f\u017ee b\u00fdt top level tag."},
+	    { "helpset.wrongParent",
+		  "P\u0159edch\u016fdce tagu {0} nem\u016f\u017ee b\u00fdt {1}."},
+	    { "helpset.unbalanced",
+		  "Nesoum\u011brn\u00fd tag {0}"},
+	    { "helpset.wrongLocale",
+		  "Upozorn\u011bn\u00ed: xml:lang atribut {0} je v konfliktu s implicitn\u00edmi hodnotami {1} a {2}"},
+	    { "helpset.unknownVersion",
+		  "Nezn\u00e1m\u00e1 verze {0}"},
+
+		// IndexView messages
+	    { "index.invalidIndexFormat",
+		  "Upozorn\u011bn\u00ed: Index m\u00e1 chybn\u00fd form\u00e1t"},
+	    { "index.unknownVersion",
+		  "Nezn\u00e1m\u00e1 verze {0}"},
+
+		// TOCView messages
+	    { "toc.wrongPublicID",
+		  "Nezn\u00e1m\u00e9 PublicID {0}"},
+	    { "toc.invalidTOCFormat",
+		  "Upozorn\u011bn\u00ed: TOC m\u00e1 chybn\u00fd form\u00e1t TOC"},
+	    { "toc.unknownVersion",
+		  "Nezn\u00e1m\u00e1 verze {0}"},
+                  
+                // FavoritesView messages
+	    { "favorites.invalidFavoritesFormat",
+		  "Upozorn\u011bn\u00ed: Nespr\u00e1vn\u00fd form\u00e1t souboru Favorites.xml"},
+	    { "favorites.unknownVersion",
+		  "Nespr\u00e1vn\u00e1 verze {0}."},
+
+		// Map messages
+	    { "map.wrongPublicID",
+		  "Nezn\u00e1m\u00e9 PublicID {0}"},
+	    { "map.invalidMapFormat",
+		  "Upozorn\u011bn\u00ed: Map m\u00e1 chybn\u00fd form\u00e1t"},
+	    { "map.unknownVersion",
+		  "Nezn\u00e1m\u00e1 verze {0}"},
+
+	    // GUI components
+	    // Labels
+	    { "index.findLabel", "Vyhledat: "},
+
+	    { "search.findLabel", "Vyhledat: "},
+	    { "search.hitDesc", "Po\u010det v\u00fdskyt\u016f v dokumentu"},
+	    { "search.qualityDesc", "Nejni\u017e\u0161\u00ed chybovost v dokumentu" },
+	    { "search.high", "Velmi vysok\u00e1"},
+	    { "search.midhigh", "Vysok\u00e1"},
+	    { "search.mid", "St\u0159edn\u00ed"},
+	    { "search.midlow", "N\u00edzk\u00e1"},
+	    { "search.low", "Velmi n\u00edzk\u00e1"},
+
+            { "favorites.add", "P\u0159idej"},
+            { "favorites.remove", "Sma\u017e"},
+            { "favorites.folder", "Slo\u017eka"},
+            { "favorites.name", "N\u00e1zev"},
+            { "favorites.cut", "Vyst\u0159ihni"},
+            { "favorites.paste", "Vlo\u017e"},
+            { "favorites.copy" ,"Kop\u00edruj" },
+            
+	    { "history.homePage", "Domovsk\u00e1 Str\u00e1nka"},
+            { "history.unknownTitle", "<nezn\u00e1m\u00fd titulek>"},
+
+	    // ToolTips
+	    { "tooltip.BackAction", "P\u0159edchoz\u00ed"},
+	    { "tooltip.ForwardAction", "N\u00e1sleduj\u00edc\u00ed"},
+	    { "tooltip.PrintAction", "Tisk"},
+	    { "tooltip.PrintSetupAction", "Nastaven\u00ed str\u00e1nky"},
+	    { "tooltip.ReloadAction", "Obnovit"},
+            { "tooltip.FavoritesAction", "P\u0159idej k obl\u00edben\u00fdm polo\u017ek\u00e1m"},
+            { "tooltip.HomeAction", "Go to home page"},
+
+	    // Accessibility names
+	    { "access.BackAction", "Sp\u00e1tky"},
+	    { "access.ForwardAction", "Vp\u0159ed"},
+	    { "access.HistoryAction", "Historie"},
+	    { "access.PrintAction", "Tisk"},
+	    { "access.PrintSetupAction", "Nastaven\u00ed Tisku"},
+	    { "access.ReloadAction", "Obnoven\u00ed"},
+            { "access.HomeAction", "Domovsk\u00e1 Str\u00e1nka"},
+            { "access.FavoritesAction", "P\u0159idej k obl\u00edben\u00fdm"},
+            { "access.contentViewer", "Prohl\u00ed\u017ee\u010d obsahu"}
+       };
+    }
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/resources/Constants_de.java b/jhMaster/JavaHelp/src/new/javax/help/resources/Constants_de.java
new file mode 100644
index 0000000000000000000000000000000000000000..6578ef769ce1ae12364588c6ab7356b52600a6fc
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/resources/Constants_de.java
@@ -0,0 +1,150 @@
+/*
+ * @(#)Constants_de.java	1.8 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+/*
+ * Constants_de.java 
+ *
+ * Originaly: Constants.java 1.8 - last change made 01/29/99
+ * Translated to German by iXOS Software AG, 03/03/1999, Martin Balin
+ */
+
+package javax.help.resources;
+
+import java.util.ListResourceBundle;
+
+/**
+ * Constants used for localizing JavaHelp
+ *
+ * These are in the form of key, value.
+ * Translators take care to only translate the values.
+ */
+
+public class Constants_de extends ListResourceBundle {
+    /**
+     * Overrides ListResourceBundle
+     */
+    public Object[][] getContents() {
+        return new Object[][] {
+	    //  Constant strings and patterns
+	    { "helpset.wrongPublicID",
+		  "Unbekannte PublicID {0}"},
+	    { "helpset.wrongTitle",
+		  "Versuche, Titel auf {0} zu setzen, aber Wert {1} ist schon gesetzt."},
+	    { "helpset.wrongHomeID",
+		  "Versuche HomeID auf {0} zu setzen, aber Wert {1} ist schon gesetzt."},
+	    { "helpset.subHelpSetTrouble",
+		  "Probleme beim Erzeugen des Subhelpset: {0}."},
+	    { "helpset.malformedURL",
+		  "Formfehler in URL: {0}."},
+	    { "helpset.incorrectURL",
+		  "Fehlerhafte URL: {0}."},
+	    { "helpset.wrongText",
+		  "{0} darf nicht den Text {1} enthalten."},
+	    { "helpset.wrongTopLevel",
+		  "{0} darf kein Top Level Tag sein."},
+	    { "helpset.wrongParent",
+		  "Parent Tag f\u00fcr {0} darf nicht {1} sein."},
+	    { "helpset.unbalanced",
+		  "Einseitiger Tag {0}."},
+	    { "helpset.wrongLocale",
+		  "Warning: xml:lang-Attribut {0} widerspricht Voreinstellung {1} und Voreinstellung {2}"},
+	    { "helpset.unknownVersion",
+		  "Unbekannte Version {0}."},
+
+		// IndexView messages
+	    { "index.invalidIndexFormat",
+		  "Warnung: Ung\u00fcltiges Index-Format"},
+	    { "index.unknownVersion",
+		  "Unbekannte Version {0}."},
+
+		// TOCView messages
+	    { "toc.wrongPublicID",
+		  "Unbekannte PublicID {0}"},
+	    { "toc.invalidTOCFormat",
+		  "Warnung: Ung\u00fcltiges Format f\u00fcr Inhaltsverzeichnis"},
+	    { "toc.unknownVersion",
+		  "Unbekannte Version {0}."},
+
+            // FavoritesView messages
+	    { "favorites.invalidFavoritesFormat",
+		  "Warnung: Ung\u00fcltiges Favorites-Format"},
+	    { "favorites.unknownVersion",
+		  "Unbekannte Version {0}."},
+
+		// Map messages
+	    { "map.wrongPublicID",
+		  "Unbekannte PublicID {0}"},
+	    { "map.invalidMapFormat",
+		  "Warnung: Ung\u00fcltiges Map-Format"},
+	    { "map.unknownVersion",
+		  "Unbekannte Version {0}."},
+
+
+	    // GUI components
+	    // Labels
+	    { "index.findLabel", "Suche: "},
+
+	    { "search.findLabel", "Suche: "},
+	    { "search.hitDesc", "Number of occurances in document"},
+	    { "search.qualityDesc", "Lowest penality value in document" },
+	    { "search.high", "High"},
+	    { "search.midhigh", "Medium high"},
+	    { "search.mid", "Medium"},
+	    { "search.midlow", "Medium low"},
+	    { "search.low", "Low"},
+            
+            { "favorites.add", "Hinzuf\u00fcgen"},
+            { "favorites.remove", "Entfernem"},
+            { "favorites.folder", "Neuer Ordner"},
+            { "favorites.name", "Name"},
+            { "favorites.cut", "Ausschneiden"},
+            { "favorites.paste", "Einf\u00fcgen"},
+            { "favorites.copy" , "Kopieren"},
+
+            { "history.homePage", "Startseite"},
+            { "history.unknownTitle", "<Unbekannter Titel>"},
+
+	    // ToolTips
+	    { "tooltip.BackAction", "Voriger"},
+	    { "tooltip.ForwardAction", "N\u00e4chster"},
+	    { "tooltip.PrintAction", "Drucken"},
+	    { "tooltip.PrintSetupAction", "Seite einrichten"},
+	    { "tooltip.ReloadAction", "Neu laden"},
+            { "tooltip.HomeAction", "Go to home page"},
+
+	    // Accessibility names
+	    { "access.BackAction", "Previous Button"},
+	    { "access.ForwardAction", "Next Button"},
+	    { "access.HistoryAction", "History Button"},
+	    { "access.PrintAction", "Print Button"},
+	    { "access.PrintSetupAction", "Page Setup Button"},
+	    { "access.ReloadAction", "Reload Button"},
+            { "access.HomeAction", "Home Button"},
+            { "access.FavoritesAction", "Add to Favorites Button"},
+            { "access.contentViewer", "Content Viewer"}
+       };
+    }
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/resources/Constants_es.java b/jhMaster/JavaHelp/src/new/javax/help/resources/Constants_es.java
new file mode 100644
index 0000000000000000000000000000000000000000..297991e206586743fd077b4793e207e5f356317e
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/resources/Constants_es.java
@@ -0,0 +1,153 @@
+/*
+ * @(#)Constants_es.java	1.3 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+/*
+ * @(#) Constants_es.java 1.3 - last change made 10/30/06
+ */
+
+package javax.help.resources;
+
+import java.util.ListResourceBundle;
+
+/**
+ * Constants used for localizing JavaHelp.
+ *
+ * These are in the form of key, value.
+ * Translators take care to only translate the values.
+ */
+
+public class Constants_es extends ListResourceBundle {
+    /**
+     * Overrides ListResourceBundle.
+     */
+    public Object[][] getContents() {
+        return new Object[][] {
+
+	    //  Constant strings and patterns
+	    { "helpset.wrongPublicID",
+		  "PublicID {0} desconocido"},
+	    { "helpset.wrongTitle",
+		  "Intentando asignar el t\u00EDtulo a {0} pero ya tiene el valor {1}."},
+	    { "helpset.wrongHomeID",
+		  "Intentando asignar homeID a {0} pero ya tiene el valor {1}."},
+	    { "helpset.subHelpSetTrouble",
+		  "Problemas creando subhelpset: {0}."},
+	    { "helpset.malformedURL",
+		  "URL mal formada: {0}."},
+	    { "helpset.incorrectURL",
+		  "URL incorrecta: {0}."},
+	    { "helpset.wrongText",
+		  "{0} no puede contener el texto {1}."},
+	    { "helpset.wrongTopLevel",
+		  "{0} no puede ser una etiqueta del nivel superior."},
+	    { "helpset.wrongParent",
+		  "La etiqueta padre de {0} no puede ser {1}."},
+	    { "helpset.unbalanced",
+		  "Etiqueta sin cerrar {0}."},
+	    { "helpset.wrongLocale",
+  "Aviso: atributo xml:lang {0} est\u00E1 en conflicto con el por defecto{1} y con {2}"},
+	    { "helpset.unknownVersion",
+		  "Versi\u00F3n desconocida {0}."},
+
+	    { "index.invalidIndexFormat",
+		  "Aviso: Formato de \u00EDndice incorrecto"},
+	    { "index.unknownVersion",
+		  "Versi\u00F3n desconocida {0}."},
+
+		// TOCView messages
+	    { "toc.wrongPublicID",
+		  "PublicID {0} desconocido"},
+	    { "toc.invalidTOCFormat",
+		  "Aviso: Formato de TOC incorrecto"},
+	    { "toc.unknownVersion",
+		  "Versi\u00F3n desconocida {0}."},
+
+            // FavoritesView messages
+	    { "favorites.invalidFavoritesFormat",
+		  "Aviso: Formato de Favoritos incorrecto"},
+	    { "favorites.unknownVersion",
+		  "Versi\u00F3n desconocida {0}."},
+
+		// Map messages
+	    { "map.wrongPublicID",
+		  "PublicID {0} desconocido"},
+	    { "map.invalidMapFormat",
+		  "Aviso: Formato de Map incorrecto"},
+	    { "map.unknownVersion",
+		  "Versi\u00F3n desconocida {0}."},
+
+	    // GUI components
+	    // Labels
+	    { "index.findLabel", "Buscar: "},
+	    { "search.findLabel", "Buscar: "},
+	    { "search.hitDesc",
+		  "N\u00FAmero de apariciones en el documento"},
+	    { "search.qualityDesc",
+		  "El m\u00E1s bajo valor de penalizaci\u00F3n en el documento" },
+	    { "search.high", "Alto"},
+	    { "search.midhigh", "Medio alto"},
+	    { "search.mid", "Medio"},
+	    { "search.midlow", "Medio bajo"},
+	    { "search.low", "Bajo"},
+
+            { "favorites.add", "Anadir"},
+            { "favorites.remove", "Quitar"},
+            { "favorites.folder", "Nueva carpeta"},
+            { "favorites.name", "Nombre"},
+            { "favorites.cut", "Cortar"},
+            { "favorites.paste", "Pegar"},
+            { "favorites.copy", "Copiar"},
+
+            { "history.homePage", "P\u00E1gina de inicio"},
+            { "history.unknownTitle",
+		  "<T\u00EDtulo de p\u00E1gina desconocido>"},
+
+            // ToolTips for Actions
+            { "tooltip.BackAction", "P\u00E1gina anterior"},
+	    { "tooltip.ForwardAction", "P\u00E1gina siguiente"},
+	    { "tooltip.PrintAction", "Imprimir"},
+	    { "tooltip.PrintSetupAction",
+		  "Configuraci\u00F3n de p\u00E1gina"},
+	    { "tooltip.ReloadAction", "Recargar"},
+            { "tooltip.FavoritesAction", "Anadir a favoritos"},
+            { "tooltip.HomeAction", "Ir a la p\u00E1gina de inicio"},
+
+	    // Accessibility names
+	    { "access.BackAction", "Bot\u00F3n de anterior"},
+	    { "access.ForwardAction", "Bot\u00F3n de siguiente"},
+	    { "access.HistoryAction", "Bot\u00F3n de historia"},
+	    { "access.PrintAction", "Bot\u00F3n de imprimir"},
+	    { "access.PrintSetupAction",
+		  "Bot\u00F3n de configuraci\u00F3n de p\u00E1gina"},
+	    { "access.ReloadAction", "Bot\u00F3n de recarga"},
+            { "access.HomeAction", "Bot\u00F3n de inicio"},
+            { "access.FavoritesAction", "Bot\u00F3n de anadir a favoritos"},
+            { "access.contentViewer", "Visualizador del contenido"}
+
+       };
+    }
+}
+
diff --git a/jhMaster/JavaHelp/src/new/javax/help/resources/Constants_fr.java b/jhMaster/JavaHelp/src/new/javax/help/resources/Constants_fr.java
new file mode 100644
index 0000000000000000000000000000000000000000..6463413a5916fd5d51e860356f9b198922a88b5d
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/resources/Constants_fr.java
@@ -0,0 +1,148 @@
+/*
+ * @(#)Constants_fr.java	1.10 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+/*
+ * @(#) Constants.java 1.11 - last change made 08/25/99
+ */
+
+package javax.help.resources;
+
+import java.util.ListResourceBundle;
+
+/**
+ * Constants used for localizing JavaHelp.
+ *
+ * These are in the form of key, value.
+ * Translators take care to only translate the values.
+ */
+
+public class Constants_fr extends ListResourceBundle {
+    /**
+     * Overrides ListResourceBundle.
+     */
+    public Object[][] getContents() {
+        return new Object[][] {
+
+	    //  Constant strings and patterns
+	    { "helpset.wrongPublicID",
+	          "ID Publique inconnue {0}"},
+	    { "helpset.wrongTitle",
+	          "Essai de r\u00e9glage du titre sur {0} mais valeur {1} existe d\u00e9j\u00e0."},
+	    { "helpset.wrongHomeID",
+	          "Essai de r\u00e9glage de l''ID domestique sur {0} mais valeur {1} existe d\u00e9j\u00e0."},
+	    { "helpset.subHelpSetTrouble",
+	          "Probl\u00e8me lors de la cr\u00e9ation de l''ensemble de sous-aide : {0}."},
+	    { "helpset.malformedURL",
+	          "URL mal form\u00e9 : {0}."},
+	    { "helpset.incorrectURL", 
+	          "URL incorrect : {0}."},
+	    { "helpset.wrongText",
+	          "{0} ne peut contenir de texte {1}."},
+	    { "helpset.wrongTopLevel",
+	          "{0} ne peut pas \u00eatre une \u00e9tiquette de haut niveau."},
+	    { "helpset.wrongParent",
+	          "L''\u00e9tiquette parent pour {0} ne peut pas \u00eatre {1}."},
+	    { "helpset.unbalanced",
+	          "\u00c9tiquette non \u00e9quilibr\u00e9e {0}."},
+	    { "helpset.wrongLocale",
+	          "Attention : xml:lang attribue {0} des conflits avec d\u00e9faut {1} et avec d\u00e9faut {2}"},
+	    { "helpset.unknownVersion",
+	          "Version inconnue {0}."},
+
+		// IndexView messages
+	    { "index.invalidIndexFormat",
+	          "Attention : format d'Index invalide"},
+	    { "index.unknownVersion",
+	          "Version inconnue {0}."},
+
+		// TOCView messages
+	    { "toc.wrongPublicID",
+	          "ID Publique inconnue {0}"},
+	    { "toc.invalidTOCFormat",
+	          "Attention : Format TOC invalide"},
+	    { "toc.unknownVersion",
+	          "Version inconnue {0}."},
+
+            // FavoritesView messages
+	    { "favorites.invalidFavoritesFormat",
+	          "Attention : Format Favorites invalide"},
+	    { "favorites.unknownVersion",
+	          "Version inconnue {0}."},
+
+		// Map messages
+	    { "map.wrongPublicID",
+	          "ID Publique inconnue {0}"},
+	    { "map.invalidMapFormat",
+	          "Attention : Format Map inconnu"},
+	    { "map.unknownVersion",
+	          "Version inconnue {0}."},
+
+	    // GUI components
+	    // Labels
+	    { "index.findLabel", "Trouver : "},
+
+	    { "search.findLabel", "Trouver : "},
+	    { "search.hitDesc", "Nombre d'apparitions dans le document"},
+	    { "search.qualityDesc", "Valeur de p\u00e9nalit\u00e9 la plus basse du document"
+},
+	    { "search.high", "Haut"},
+	    { "search.midhigh", "Moyen haut"},
+	    { "search.mid", "Moyen"},
+	    { "search.midlow", "Moyen bas"},
+	    { "search.low", "Bas"},
+
+            { "favorites.add", "Ajouter"},
+            { "favorites.remove", "Supprimer"},
+            { "favorites.folder", "Nouveau dossier"},
+            { "favorites.name", "Nom"},
+            { "favorites.cut", "Couper"},
+            { "favorites.paste", "Coller"},
+            { "favorites.copy" , "Copier"},
+
+            { "history.homePage", "Page de d\u00e9marrage"},
+            { "history.unknownTitle", "Page inconnue>"},
+
+	    // ToolTips for Actions
+	    { "tooltip.BackAction", "Pr\u00e9c\u00e9dent"},
+	    { "tooltip.ForwardAction", "Suivant"},
+	    { "tooltip.PrintAction", "Imprimer"},
+	    { "tooltip.PrintSetupAction", "Mise en page"},
+	    { "tooltip.ReloadAction", "Recharger"},
+            { "tooltip.HomeAction", "Vers page ded\u00e9marrage"},
+
+	    // Accessibility names
+	    { "access.BackAction", "Bouton Pr\00e9c\00e9dent"},
+	    { "access.ForwardAction", "Bouton Suivant"},
+	    { "access.HistoryAction", "Bouton Historique"},
+	    { "access.PrintAction", "Bouton Impression"},
+	    { "access.PrintSetupAction", "Bouton Mise en page"},
+	    { "access.ReloadAction", " Bouton Actualiser"},
+            { "access.HomeAction", "Bouton Page de d\u00e9marrage"},
+            { "access.FavoritesAction", "Bouton Ajouter aux favoris"},
+            { "access.contentViewer", "Visualiser le contenu"}
+       };
+    }
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/resources/Constants_he.java b/jhMaster/JavaHelp/src/new/javax/help/resources/Constants_he.java
new file mode 100644
index 0000000000000000000000000000000000000000..585e0b5bb66199b6d54feeccd10c64a82cfeaf0b
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/resources/Constants_he.java
@@ -0,0 +1,149 @@
+/*
+ * @(#)Constants_he.java	1.2 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+/*
+ * @(#) Constants_he.java 1.19 - last change made 10/19/01
+ */
+
+package javax.help.resources;
+
+import java.util.ListResourceBundle;
+
+/**
+ * Constants used for localizing JavaHelp.
+ *
+ * These are in the form of key, value.
+ * Translators take care to only translate the values.
+ */
+
+public class Constants_he extends ListResourceBundle {
+    /**
+     * Overrides ListResourceBundle.
+     */
+    public Object[][] getContents() {
+        return new Object[][] {
+
+	    //  Constant strings and patterns
+	    { "helpset.wrongPublicID",
+		  "PublicID {0} \u05dc\u05d0 \u05d9\u05d3\u05d5\u05e2"},
+	    { "helpset.wrongTitle",
+		  "\u05de\u05e0\u05e1\u05d4 \u05dc\u05d4\u05d2\u05d3\u05d9\u05e8 \u05d0\u05ea \u05d4\u05db\u05d5\u05ea\u05e8\u05ea \u05db {0} \u05d0\u05da \u05db\u05d1\u05e8 \u05d4\u05d5\u05d2\u05d3\u05e8\u05d4 \u05db {1}."},
+	    { "helpset.wrongHomeID",
+		  " homeID \u05db {0} \u05d0\u05da \u05db\u05d1\u05e8 \u05d4\u05d5\u05d2\u05d3\u05e8 \u05db {1}."},
+	    { "helpset.subHelpSetTrouble",
+		  "\u05d1\u05e2\u05d9\u05d5\u05ea \u05d1\u05d9\u05e6\u05d9\u05e8\u05ea \u05ea\u05ea-\u05e2\u05e8\u05db\u05ea \u05e2\u05d6\u05e8\u05d4:{0}.-"},
+	    { "helpset.malformedURL",
+		  "\u05db\u05ea\u05d5\u05d1\u05ea URL \u05d0\u05d9\u05e0\u05d4 \u05de\u05e2\u05d5\u05e6\u05d1\u05ea \u05db\u05e8\u05d0\u05d5\u05d9:{0}."},
+	    { "helpset.incorrectURL",
+		  "\u05db\u05ea\u05d5\u05d1\u05ea URL \u05e9\u05d2\u05d5\u05d9\u05d4"},
+	    { "helpset.wrongText",
+		  "{0} \u05d0\u05d9\u05e0\u05d4 \u05d9\u05db\u05d5\u05dc\u05d4 \u05dc\u05d4\u05db\u05d9\u05dc \u05db\u05d9\u05ea\u05d5\u05d1 {1}."},
+	    { "helpset.wrongTopLevel",
+		  "{0} \u05d0\u05d9\u05e0\u05d4 \u05d9\u05db\u05d5\u05dc\u05d4 \u05dc\u05d4\u05d9\u05d5\u05ea \u05ea\u05d2\u05d9\u05ea \u05d1\u05e8\u05de\u05d4 \u05e2\u05dc\u05d9\u05d5\u05e0\u05d4."},
+	    { "helpset.wrongParent",
+		  "\u05ea\u05d2\u05d9\u05ea \u05d4\u05d0\u05dd \u05e9\u05dc {0} \u05dc\u05d0 \u05d9\u05db\u05d5\u05dc\u05d4 \u05dc\u05d4\u05d9\u05d5\u05ea {1}."},
+	    { "helpset.unbalanced",
+		  "\u05ea\u05d2\u05d9\u05ea \u05d1\u05dc\u05ea\u05d9 \u05de\u05d0\u05d5\u05d6\u05e0\u05ea {0}."},
+	    { "helpset.wrongLocale",
+		  "\u05d0\u05d6\u05d4\u05e8\u05d4: \u05de\u05d0\u05e4\u05d9\u05d9\u05df xml:lang {0} \u05de\u05ea\u05e0\u05d2\u05e9 \u05e2\u05dd \u05d1\u05e8\u05d9\u05e8\u05ea \u05de\u05d7\u05d3\u05dc {1} \u05d5\u05e2\u05dd \u05d1\u05e8\u05d9\u05e8\u05ea \u05de\u05d7\u05d3\u05dc {2}."},
+	    { "helpset.unknownVersion",
+		  " \u05d2\u05d9\u05e8\u05e1\u05d4 \u05d1\u05dc\u05ea\u05d9 \u05d9\u05d3\u05d5\u05e2\u05d4 {0}."},
+
+		// IndexView messages
+	    { "index.invalidIndexFormat",
+		  "\u05d0\u05d6\u05d4\u05e8\u05d4: \u05e6\u05d5\u05e8\u05ea \u05d0\u05d9\u05e0\u05d3\u05e7\u05e1 \u05dc\u05d0 \u05d7\u05d5\u05e7\u05d9\u05ea"},
+	    { "index.unknownVersion",
+		  "\u05d2\u05d9\u05e8\u05e1\u05d4 \u05d1\u05dc\u05ea\u05d9 \u05d9\u05d3\u05d5\u05e2\u05d4 {0}."},
+
+		// TOCView messages
+	    { "toc.wrongPublicID",
+		  "PublicID {0} \u05d1\u05dc\u05ea\u05d9 \u05d9\u05d3\u05d5\u05e2\u05d4"},
+	    { "toc.invalidTOCFormat",
+		  "\u05d0\u05d6\u05d4\u05e8\u05d4: \u05e6\u05d5\u05e8\u05ea \u05ea\u05d5\u05db\u05df \u05e2\u05e0\u05d9\u05e0\u05d9\u05dd \u05dc\u05d0 \u05d7\u05d5\u05e7\u05d9\u05ea"},
+	    { "toc.unknownVersion",
+		  "\u05d2\u05d9\u05e8\u05e1\u05d4 \u05d1\u05dc\u05ea\u05d9 \u05d9\u05d3\u05d5\u05e2\u05d4 {0}."},
+                  
+            // FavoritesView messages
+	    { "favorites.invalidFavoritesFormat",
+		  "\u05d0\u05d6\u05d4\u05e8\u05d4: \u05e6\u05d5\u05e8\u05ea \u05de\u05d5\u05e2\u05d3\u05e4\u05d9\u05dd \u05dc\u05d0 \u05d7\u05d5\u05e7\u05d9\u05ea"},
+	    { "favorites.unknownVersion",
+		  "\u05d2\u05d9\u05e8\u05e1\u05d4 \u05d1\u05dc\u05ea\u05d9 \u05d9\u05d3\u05d5\u05e2\u05d4 {0}."},
+
+		// Map messages
+	    { "map.wrongPublicID",
+		  "PublicID {0} \u05d1\u05dc\u05ea\u05d9 \u05d9\u05d3\u05d5\u05e2\u05d4"},
+	    { "map.invalidMapFormat",
+		  "\u05d0\u05d6\u05d4\u05e8\u05d4: \u05e6\u05d5\u05e8\u05ea \u05de\u05e4\u05ea \u05dc\u05d0 \u05d7\u05d5\u05e7\u05d9\u05ea"},
+	    { "map.unknownVersion",
+		  "\u05d2\u05d9\u05e8\u05e1\u05d4 \u05d1\u05dc\u05ea\u05d9 \u05d9\u05d3\u05d5\u05e2\u05d4 {0}."},
+
+	    // GUI components
+	    // Labels
+	    { "index.findLabel", "\u05d7\u05e4\u05e9: "},
+            
+	    { "search.findLabel", "\u05d7\u05e4\u05e9: "},
+	    { "search.hitDesc", "\u05de\u05e1\u05e4\u05e8 \u05de\u05d5\u05e4\u05e2\u05d9\u05dd \u05d1\u05de\u05e1\u05de\u05da"},
+	    { "search.qualityDesc", "\u05e2\u05e8\u05da \u05d4\u05e7\u05e0\u05e1 \u05d4\u05e0\u05de\u05d5\u05da \u05d1\u05d9\u05d5\u05ea\u05e8 \u05d1\u05de\u05e1\u05de\u05da" },
+	    { "search.high", "\u05d2\u05d1\u05d5\u05d4"},
+	    { "search.midhigh", "\u05d1\u05d9\u05e0\u05d5\u05e0\u05d9 \u05d2\u05d1\u05d5\u05d4"},
+	    { "search.mid", "\u05d1\u05d9\u05e0\u05d5\u05e0\u05d9"},
+	    { "search.midlow", "\u05d1\u05d9\u05e0\u05d5\u05e0\u05d9 \u05e0\u05de\u05d5\u05da"},
+	    { "search.low", "\u05e0\u05de\u05d5\u05da"},
+            
+            { "favorites.add", "\u05d4\u05d5\u05e1\u05e4\u05d4"},
+            { "favorites.remove", "\u05d4\u05e1\u05e8\u05d4"},
+            { "favorites.folder", "\u05ea\u05d9\u05e7\u05d9\u05d4 \u05d7\u05d3\u05e9\u05d4"},
+            { "favorites.name", "\u05e9\u05dd/\u05de\u05ea\u05df \u05e9\u05dd"},
+            { "favorites.cut", "\u05d2\u05d6\u05d9\u05e8\u05d4"},
+            { "favorites.paste", "\u05d4\u05d3\u05d1\u05e7\u05d4"},
+            { "favorites.copy" , "\u05d4\u05e2\u05ea\u05e7\u05d4"},
+
+            { "history.homePage", "\u05d3\u05e3 \u05d4\u05d1\u05d9\u05ea"},
+            { "history.unknownTitle", "<\u05db\u05d5\u05ea\u05e8\u05ea \u05d3\u05e3 \u05d0\u05d9\u05e0\u05d4 \u05d9\u05d3\u05d5\u05e2\u05d4>"},
+
+            // ToolTips for Actions
+            { "tooltip.BackAction", "\u05d4\u05d3\u05e3 \u05d4\u05e7\u05d5\u05d3\u05dd"},
+	    { "tooltip.ForwardAction", "\u05d4\u05d3\u05e3 \u05d4\u05d1\u05d0"},
+	    { "tooltip.PrintAction", "\u05d4\u05d3\u05e4\u05e1\u05d4"},
+	    { "tooltip.PrintSetupAction", "\u05d4\u05d2\u05d3\u05e8\u05ea \u05e2\u05de\u05d5\u05d3"},
+	    { "tooltip.ReloadAction", "\u05d8\u05e2\u05d9\u05e0\u05d4 \u05de\u05d7\u05d3\u05e9"},
+            { "tooltip.FavoritesAction", "\u05d4\u05d5\u05e1\u05e4\u05d4 \u05dc\u05de\u05d5\u05e2\u05d3\u05e4\u05d9\u05dd"},
+            { "tooltip.HomeAction", "\u05e2\u05d1\u05d5\u05e8 \u05dc\u05d3\u05e3 \u05d4\u05d1\u05d9\u05ea"},
+
+	    // Accessibility names
+	    { "access.BackAction", "\u05d4\u05db\u05e4\u05ea\u05d5\u05e8 \u05d4\u05e7\u05d5\u05d3\u05dd"},
+	    { "access.ForwardAction", "\u05d4\u05db\u05e4\u05ea\u05d5\u05e8 \u05d4\u05d1\u05d0"},
+	    { "access.HistoryAction", "\u05db\u05e4\u05ea\u05d5\u05e8 \u05d4\u05e1\u05d8\u05d5\u05e8\u05d9\u05d4"},
+	    { "access.PrintAction", "\u05db\u05e4\u05ea\u05d5\u05e8 \u05d4\u05d3\u05e4\u05e1\u05d4"},
+	    { "access.PrintSetupAction", "\u05db\u05e4\u05ea\u05d5\u05e8 \u05d4\u05d2\u05d3\u05e8\u05ea \u05e2\u05de\u05d5\u05d3"},
+	    { "access.ReloadAction", "\u05db\u05e4\u05ea\u05d5\u05e8 \u05d8\u05e2\u05d9\u05e0\u05d4 \u05de\u05d7\u05d3\u05e9"},
+            { "access.HomeAction", "\u05db\u05e4\u05ea\u05d5\u05e8 \u05d4\u05d1\u05d9\u05ea"},
+            { "access.FavoritesAction", "\u05db\u05e4\u05ea\u05d5\u05e8 \u05d4\u05d5\u05e1\u05e4\u05d4 \u05dc\u05de\u05d5\u05e2\u05d3\u05e4\u05d9\u05dd"},
+            { "access.contentViewer", "\u05ea\u05d5\u05db\u05e0\u05ea \u05e6\u05e4\u05d9\u05d9\u05d4 \u05d1\u05ea\u05d5\u05db\u05df"}
+
+       };
+    }
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/resources/Constants_ja.java b/jhMaster/JavaHelp/src/new/javax/help/resources/Constants_ja.java
new file mode 100644
index 0000000000000000000000000000000000000000..07c516a820176657578b9a856d6f238c80d971bf
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/resources/Constants_ja.java
@@ -0,0 +1,119 @@
+/*
+ * @(#)Constants_ja.java	1.10 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+/*
+ * @(#) Constants_ja.java 1.10 - last change made 10/30/06
+ */
+
+package javax.help.resources;
+
+import java.util.ListResourceBundle;
+
+/**
+ * \u5b9a\u6570\u306f\u3001JavaHelp \u3092\u30ed\u30fc\u30ab\u30e9\u30a4\u30ba\u3059\u308b\u306e\u306b\u4f7f\u7528\u3055\u308c\u307e\u3059\u3002
+ *
+ * \u5b9a\u6570\u306f\u3001\u30ad\u30fc\u3001\u5024\u306e\u5f62\u3067\u793a\u3055\u308c\u307e\u3059\u3002
+ * \u5024\u3060\u3051\u3092\u7ffb\u8a33\u3057\u307e\u3059\u3002
+ */
+
+public class Constants_ja extends ListResourceBundle {
+    /**
+     * ListResourceBundle \u3092\u4e0a\u66f8\u304d\u3057\u307e\u3059\u3002
+     */
+    public Object[][] getContents() {
+        return new Object[][] {
+
+	    // \u5b9a\u6570\u6587\u5b57\u5217\u3068\u30d1\u30bf\u30fc\u30f3 
+	    { "helpset.wrongTitle",
+		  "\u30bf\u30a4\u30c8\u30eb\u3092 {0} \u306b\u8a2d\u5b9a\u3057\u3088\u3046\u3068\u3057\u307e\u3057\u305f\u304c\u3001\u3059\u3067\u306b\u5024 {1} \u304c\u5b58\u5728\u3057\u3066\u3044\u307e\u3059\u3002"},
+	    { "helpset.wrongHomeID",
+		  "homeID \u3092 {0} \u306b\u8a2d\u5b9a\u3057\u3088\u3046\u3068\u3057\u307e\u3057\u305f\u304c\u3001\u3059\u3067\u306b\u5024 {1} \u304c\u5b58\u5728\u3057\u3066\u3044\u307e\u3059\u3002"},
+	    { "helpset.subHelpSetTrouble",
+		  "\u30b5\u30d6\u30d8\u30eb\u30d7\u30bb\u30c3\u30c8: {0} \u306e\u4f5c\u6210\u306b\u554f\u984c\u304c\u3042\u308a\u307e\u3059\u3002"},
+	    { "helpset.malformedURL",
+		  "URL: {0} \u306e\u5f62\u5f0f\u304c\u6b63\u3057\u304f\u3042\u308a\u307e\u305b\u3093\u3002"},
+	    { "helpset.incorrectURL",
+		  "URL: {0} \u306f\u9593\u9055\u3063\u3066\u3044\u307e\u3059\u3002"},
+	    { "helpset.wrongText",
+		  "{0} \u306b\u306f\u30c6\u30ad\u30b9\u30c8 {1} \u3092\u542b\u3080\u3053\u3068\u306f\u3067\u304d\u307e\u305b\u3093\u3002"},
+	    { "helpset.wrongTopLevel",
+		  "{0} \u306f\u6700\u4e0a\u4f4d\u30ec\u30d9\u30eb\u306e\u30bf\u30b0\u306b\u306f\u306a\u308c\u307e\u305b\u3093\u3002"},
+	    { "helpset.wrongParent",
+		  "{0} \u306e\u89aa\u30bf\u30b0\u306f {1} \u306b\u306f\u306a\u308c\u307e\u305b\u3093\u3002"},
+	    { "helpset.unbalanced",
+		  "\u30bf\u30b0 {0} \u306f\u9589\u3058\u3066\u3044\u307e\u305b\u3093\u3002"},
+	    { "helpset.wrongLocale",
+		  "\u8b66\u544a: xml: \u8a00\u8a9e\u5c5e\u6027 {0} \u306f\u3001\u30c7\u30d5\u30a9\u30eb\u30c8\u306e {1} \u304a\u3088\u3073 {2} \u3068\u91cd\u8907\u3057\u307e\u3059\u3002"},
+
+	    { "index.invalidIndexFormat",
+		  "\u8b66\u544a: \u7d22\u5f15\u306e\u30d5\u30a9\u30fc\u30de\u30c3\u30c8\u304c\u6b63\u3057\u304f\u3042\u308a\u307e\u305b\u3093\u3002"},
+
+	    { "toc.invalidTOCFormat",
+		  "\u8b66\u544a: \u76ee\u6b21\u306e\u30d5\u30a9\u30fc\u30de\u30c3\u30c8\u304c\u304c\u6b63\u3057\u304f\u3042\u308a\u307e\u305b\u3093\u3002"},
+
+	    // GUI \u30b3\u30f3\u30dd\u30fc\u30cd\u30f3\u30c8 
+	    // \u30e9\u30d9\u30eb 
+	    { "index.findLabel", "\u691c\u7d22 : "},
+
+	    { "search.findLabel", "\u691c\u7d22 : "},
+	    { "search.hitDesc", "Number of occurances in document"},
+	    { "search.qualityDesc", "Lowest penality value in document" },
+	    { "search.high", "High"},
+	    { "search.midhigh", "Medium high"},
+	    { "search.mid", "Medium"},
+	    { "search.midlow", "Medium low"},
+	    { "search.low", "Low"},
+            
+            { "favorites.add", "\u8ffd\u52a0"},
+            { "favorites.remove", "\u524a\u9664"},
+            { "favorites.folder", "\u65b0\u898f\u30df=u30a9\u30eb\u30c0\u30fc\u306e\u4f5c\u6210"},
+            { "favorites.name", "\u540d]u524d"},
+            { "favorites.cut", "u5207\u308a\u53d6\u308a"},
+            { "favorites.paste", "\u8cbc\u308a\u4ed8\u3051"},
+            { "favorites.copy" , "u30b3\u30d4\u30fc"},
+
+	    // ToolTips for Action
+	    { "tooltip.BactionAction", "\u524d\u306e\u30da\u30fc\u30b8"},
+	    { "tooltip.ForwardAction", "\u6b21\u306e\u30da\u30fc\u30b8"},
+	    { "tooltip.PrintAction", "\u5370\u5237"},
+	    { "tooltip.PrintSetupAction", "\u30da\u30fc\u30b8\u8a2d\u5b9a"},
+	    { "tooltip.ReloadAction", "\u518d\u8aad\u307f\u8fbc\u307f"},
+            { "tooltip.FavoritesAction", "\u304a\u6c17\u306b\u5165\u308a\u306b\u8ffd\u52a0"},
+            { "tooltip.HomeAction", "\u30db\u30fc\u30e0\u30da\u30fc\u30b8\u3078\u79fb\u52d5"},
+
+	    // Accessibility names
+	    { "access.BackAction", "Previous Button"},
+	    { "access.ForwardAction", "Next Button"},
+	    { "access.HistoryAction", "History Button"},
+	    { "access.PrintAction", "Print Button"},
+	    { "access.PrintSetupAction", "Page Setup Button"},
+	    { "access.ReloadAction", "Reload Button"},
+            { "access.HomeAction", "Home Button"},
+            { "access.FavoritesAction", "Add to Favorites Button"},
+            { "access.contentViewer", "Content Viewer"}
+       };
+    }
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/resources/Constants_pl.java b/jhMaster/JavaHelp/src/new/javax/help/resources/Constants_pl.java
new file mode 100644
index 0000000000000000000000000000000000000000..97024c5f8d77eaf7e5100d51db963e461b9e076d
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/resources/Constants_pl.java
@@ -0,0 +1,173 @@
+/*
+ * @(#)Constants_pl.java	1.2 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help.resources;
+
+import java.util.ListResourceBundle;
+
+/**
+ * 
+ * Constants used for localizing JavaHelp.
+ *
+ * These are in the form of key, value.
+ * Translators take care to only translate the values.
+ * 
+ * @author Krystian Nowak
+ * @author krystian (at) man (dot) poznan (dot) pl
+ * 
+ */
+
+//
+// Polish diacritical characters in Unicode
+//
+// A - 0104  a - 0105
+// C - 0106  c - 0107
+// E - 0118  e - 0119
+// L - 0141  l - 0142
+// N - 0143  n - 0144
+// O - 00D3  o - 00F3
+// S - 015A  s - 015B
+// X - 0179  x - 017A
+// Z - 017B  z - 017C
+
+public class Constants_pl extends ListResourceBundle {
+    /**
+     * Overrides ListResourceBundle.
+     */
+    public Object[][] getContents() {
+        return new Object[][] {
+
+	    //  Constant strings and patterns
+	    { "helpset.wrongPublicID",
+		  "Nieznane PublicID {0}"},
+	    { "helpset.wrongTitle",
+		  "Pr\u00F3ba ustawienia tytu\u0142u na {0} mimo, \u017Ce ma ju \u017C warto\u015B\u0107 {1}."},
+	    { "helpset.wrongHomeID",
+		  "Pr\u00F3ba ustawienia homeID na {0} mimo, \u017Ce ma ju \u017C warto\u015B\u0107 {1}."},
+	    { "helpset.subHelpSetTrouble",
+		  "B\u0142\u0105d w trakcie tworzenia podpomocy: {0}."},
+	    { "helpset.malformedURL",
+		  "\u0179le sformu\u0142owany URL: {0}."},
+	    { "helpset.incorrectURL",
+		  "Niepoprawny URL: {0}."},
+	    { "helpset.wrongText",
+		  "{0} nie mo\u017Ce zawiera\u0107 tekstu {1}."},
+	    { "helpset.wrongTopLevel",
+		  "{0} nie mo\u017Ce by\u0107 znacznikiem najwy\u017Cszego poziomu."},
+	    { "helpset.wrongParent",
+		  "{1} nie mo\u017Ce by\u0107 nadznacznikiem dla {0}."},
+	    { "helpset.unbalanced",
+		  "Niezbalansowany znacznik {0}."},
+	    { "helpset.wrongLocale",
+		  "Uwaga: atrybut xml:lang {0} jest w konflikcie z domy\u015Blnym {1} i domy\u015Blnym {2}"},
+	    { "helpset.unknownVersion",
+		  "Nieznana wersja {0}."},
+
+		// IndexView messages
+	    { "index.invalidIndexFormat",
+		  "Uwaga: Index ma nieprawid\u0142owy format"},
+	    { "index.unknownVersion",
+		  "Nieznana wersja {0}."},
+
+		// TOCView messages
+	    { "toc.wrongPublicID",
+		  "Nieznany PublicID {0}"},
+	    { "toc.invalidTOCFormat",
+		  "Uwaga: TOC ma nieprawid\u0142owy format"},
+	    { "toc.unknownVersion",
+		  "Nieznana wersja {0}."},
+                  
+            // FavoritesView messages
+	    { "favorites.invalidFavoritesFormat",
+		  "Uwaga: Plik Favorites.xml ma nieprawid\u0142owy format"},
+	    { "favorites.unknownVersion",
+		  "Nieznana wersja {0}."},
+
+		// Map messages
+	    { "map.wrongPublicID",
+		  "Nieznane PublicID {0}"},
+	    { "map.invalidMapFormat",
+		  "Uwaga: Map ma nieprawid\u0142owy format"},
+	    { "map.unknownVersion",
+		  "Nieznana wersja {0}."},
+
+
+	    // GUI components
+	    // Labels
+	    { "index.findLabel", "Znajd\u017A: "},
+            
+	    { "search.findLabel", "Znajd\u017A: "},
+	    { "search.hitDesc", "Liczba wyst\u0105pie\u0144 w dokumencie"},
+	    { "search.qualityDesc", "Miara niedok\u0142adno\u015Bci" },
+	    { "search.high", "Najwy\u017Csza"},
+	    { "search.midhigh", "Wysoka"},
+	    { "search.mid", "\u015Arednia"},
+	    { "search.midlow", "Niska"},
+	    { "search.low", "Najni\u017Csza"},
+            
+            { "favorites.add", "Dodaj"},
+            { "favorites.remove", "Usu\u0144"},
+            { "favorites.folder", "Nowy folder"},
+            { "favorites.name", "Nazwa"},
+            { "favorites.cut", "Wytnij"},
+            { "favorites.paste", "Wklej"},
+            { "favorites.copy" , "Kopiuj"},
+
+            { "history.homePage", "Strona domowa"},
+            { "history.unknownTitle", "<nieznany tytu\u0142 strony>"},
+
+            // ToolTips for Actions
+            { "tooltip.BackAction", "Poprzednia strona"},
+	    { "tooltip.ForwardAction", "Nast\u0119pna strona"},
+	    { "tooltip.PrintAction", "Drukuj"},
+	    { "tooltip.PrintSetupAction", "Ustawienia strony"},
+	    { "tooltip.ReloadAction", "Prze\u0142aduj"},
+            { "tooltip.FavoritesAction", "Dodaj do ulubionych"},
+            { "tooltip.HomeAction", "Id\u017A do strony domowej"},
+
+	    // Accessibility names
+	    { "access.BackAction", "Do ty\u0142u"},
+	    { "access.ForwardAction", "Nast\u0119pny"},
+	    { "access.HistoryAction", "Historia"},
+	    { "access.PrintAction", "Drukuj"},
+	    { "access.PrintSetupAction", "Ustawienia stron"},
+	    { "access.ReloadAction", "Prze\u0142aduj"},
+            { "access.HomeAction", "Strona domowa"},
+            { "access.FavoritesAction", "Dodaj do ulubionych"},
+            { "access.contentViewer", "Przegl\u0105darka zawarto\u015Bci"}
+
+       };
+    }
+}
+
+
+
+
+
+
+
+
diff --git a/jhMaster/JavaHelp/src/new/javax/help/resources/Constants_ru.java b/jhMaster/JavaHelp/src/new/javax/help/resources/Constants_ru.java
new file mode 100644
index 0000000000000000000000000000000000000000..1f6c9763deac536e6c3657f9fb7ae0c06624bd8d
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/resources/Constants_ru.java
@@ -0,0 +1,148 @@
+/*
+ * @(#)Constants_ru.java	1.8 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+/*
+ * @(#) Constants_ru.java 1.8 - last change made 10/30/06
+ * @(#) Constants.java 1.8 - last change made 01/29/99
+ */
+
+package javax.help.resources;
+
+import java.util.ListResourceBundle;
+
+/**
+ * Constants used for localizing JavaHelp
+ *
+ * These are in the form of key, value.
+ * Translators take care to only translate the values
+ */
+
+public class Constants_ru extends ListResourceBundle {
+    /**
+     * Overrides ListResourceBundle
+     */
+    public Object[][] getContents() {
+        return new Object[][] {
+
+            //  Constant strings and patterns
+            { "helpset.wrongPublicID",
+                  "\u041d\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b\u0439 PublicID {0}"},
+            { "helpset.wrongTitle",
+                  "\u041d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 title \u043d\u0430 {0} \u0442\u0430\u043a \u043a\u0430\u043a \u043e\u043d \u0443\u0436\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d \u0432 {1}."},
+            { "helpset.wrongHomeID",
+                  "\u041d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 homeID \u043d\u0430 {0} \u0442\u0430\u043a \u043a\u0430\u043a \u043e\u043d \u0443\u0436\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d \u0432 {1}."},
+            { "helpset.subHelpSetTrouble",
+                  "\u041e\u0448\u0438\u0431\u043a\u0430 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f subhelpset: {0}."},
+            { "helpset.malformedURL",
+                  "\u041e\u0448\u0438\u0431\u043e\u0447\u043d\u044b\u0439 URL: {0}."},
+            { "helpset.incorrectURL",
+                  "\u041d\u0435\u0432\u0435\u0440\u043d\u044b\u0439 URL: {0}."},
+            { "helpset.wrongText",
+                  "{0} \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0442\u0435\u043a\u0441\u0442 {1}."},
+            { "helpset.wrongTopLevel",
+                  "{0} \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0442\u0435\u0433\u043e\u043c \u0432\u0435\u0440\u0445\u043d\u0435\u0433\u043e \u0443\u0440\u043e\u0432\u043d\u044f."},
+            { "helpset.wrongParent",
+                  "\u0420\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u0442\u0435\u0433 {0} \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c {1}."},
+            { "helpset.unbalanced",
+                  "\u041d\u0435\u0437\u0430\u043a\u0440\u044b\u0442\u044b\u0439 \u0442\u0435\u0433 {0}."},
+            { "helpset.wrongLocale",
+                  "\u041f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u0435: xml: \u044f\u0437\u044b\u043a\u043e\u0432\u043e\u0439 \u0430\u0442\u0440\u0438\u0431\u0443\u0442 {0} \u043d\u0435 \u0441\u043e\u0433\u043b\u0430\u0441\u0443\u0435\u0442\u0441\u044f \u0441 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u043c \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e {1} \u0438 {2}"},
+            { "helpset.unknownVersion",
+                  "\u041d\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043d\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f {0}."},
+
+                // IndexView messages
+            { "index.invalidIndexFormat",
+                  "\u041f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u0435: \u041d\u0435\u0432\u0435\u0440\u043d\u044b\u0439 \u0444\u043e\u0440\u043c\u0430\u0442 \u0438\u043d\u0434\u0435\u043a\u0441\u0430"},
+            { "index.unknownVersion",
+                  "\u041d\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043d\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f {0}."},
+
+                // TOCView messages
+            { "toc.wrongPublicID",
+                  "\u041d\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b\u0439 PublicID {0}"},
+            { "toc.invalidTOCFormat",
+                  "\u041f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u0435: \u041d\u0435\u0432\u0435\u0440\u043d\u044b\u0439 \u0444\u043e\u0440\u043c\u0430\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u044f"},
+            { "toc.unknownVersion",
+                  "\u041d\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043d\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f {0}."},
+
+            // FavoritesView messages
+	    { "favorites.invalidFavoritesFormat",
+		  "Warning: Invalid Favorites format"},
+	    { "favorites.unknownVersion",
+		  "Unknown Version {0}."},
+
+                // Map messages
+            { "map.wrongPublicID",
+                  "\u041d\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b\u0439  PublicID {0}"},
+            { "map.invalidMapFormat",
+                  "\u041f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u0435: \u041d\u0435\u0432\u0435\u0440\u043d\u044b\u0439 \u0444\u043e\u0440\u043c\u0430\u0442 \u043a\u0430\u0440\u0442\u044b"},
+            { "map.unknownVersion",
+                  "\u041d\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043d\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f {0}."},
+
+            // GUI components
+            // Labels
+            { "index.findLabel", "\u041d\u0430\u0439\u0442\u0438: "},
+
+            { "search.findLabel", "\u041d\u0430\u0439\u0442\u0438: "},
+ 	    { "search.hitDesc", "Number of occurances in document"},
+	    { "search.qualityDesc", "Lowest penality value in document" },
+	    { "search.high", "High"},
+	    { "search.midhigh", "Medium high"},
+	    { "search.mid", "Medium"},
+	    { "search.midlow", "Medium low"},
+	    { "search.low", "Low"},
+            
+            { "favorites.add", "Add"},
+            { "favorites.remove", "Remove"},
+            { "favorites.folder", "New Folder"},
+            { "favorites.name", "Name"},
+            { "favorites.cut", "Cut"},
+            { "favorites.paste", "Paste"},
+            { "favorites.copy" , "Copy"},
+
+            { "history.homePage", "Home page"},
+            { "history.unknownTitle", "<unknown page title>"},
+
+           // ToolTips
+            { "tooltip.BackAction", "\u043d\u0430\u0437\u0430\u0434"},
+            { "tooltip.ForwardAction", "\u0432\u043f\u0435\u0440\u0435\u0434"},
+            { "tooltip.PrintAction", "\u043f\u0435\u0447\u0430\u0442\u044c"},
+	    { "tooltip.PrintSetupAction", "\u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b"},
+            { "tooltip.ReloadAction", "\u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c"},
+            { "tooltip.HomeAction", "Go to home page"},
+
+	    // Accessibility names
+	    { "access.BackAction", "Previous Button"},
+	    { "access.ForwardAction", "Next Button"},
+	    { "access.HistoryAction", "History Button"},
+	    { "access.PrintAction", "Print Button"},
+	    { "access.PrintSetupAction", "Page Setup Button"},
+	    { "access.ReloadAction", "Reload Button"},
+            { "access.HomeAction", "Home Button"},
+            { "access.FavoritesAction", "Add to Favorites Button"},
+            { "access.contentViewer", "Content Viewer"}
+       };
+    }
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/resources/Constants_sk.java b/jhMaster/JavaHelp/src/new/javax/help/resources/Constants_sk.java
new file mode 100644
index 0000000000000000000000000000000000000000..53b9f1cfd6ab4f03ff489f880975d6508ace0e2b
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/resources/Constants_sk.java
@@ -0,0 +1,153 @@
+/*
+ * @(#)Constants_sk.java	1.10 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help.resources;
+
+import java.util.ListResourceBundle;
+
+/**
+ * Constants used for localizing JavaHelp.
+ *
+ * These are in the form of key, value.
+ * Translators take care to only translate the values.
+ *
+ * @author Richard Gregor 
+ * @version	1.10	10/30/06
+ *
+ */
+
+public class Constants_sk extends ListResourceBundle {
+    /**
+     * Overrides ListResourceBundle.
+     */
+    public Object[][] getContents() {
+        return new Object[][] {
+
+	    //  Constant strings and patterns
+	    { "helpset.wrongPublicID",
+		  "Nezn\u00e1me PublicID {0}"},
+	    { "helpset.wrongTitle",
+		  "Pokus o nastavenie Title na {0} Title u\u017E m\u00e1 hodnotu {1}."},
+	    { "helpset.wrongHomeID",
+		  "Pokus o nastavenie homeID na {0} homeID u\u017E m\u00e1 hodnotu {1}."},
+	    { "helpset.subHelpSetTrouble",
+		  "Probl\u00e9m pri vytv\u00e1ran\u00ed subhelpsetu: {0}."},
+	    { "helpset.malformedURL",
+		  "Chybn\u00fd form\u00e1t URL: {0}."},
+	    { "helpset.incorrectURL",
+		  "Nespr\u00e1vne URL: {0}."},
+	    { "helpset.wrongText",
+		  "{0} nem\u00f4\u017Ee obsahova\u0165 text {1}."},
+	    { "helpset.wrongTopLevel",
+		  "{0} Nespr\u00e1vny top level tag."},
+	    { "helpset.wrongParent",
+		  "Rodi\u010Dovsk\u00fd tag {0} nem\u00f4\u017Ee by\u0165 {1}."},
+	    { "helpset.unbalanced",
+		  "Neukon\u010Den\u00fd tag {0}."},
+	    { "helpset.wrongLocale",
+		  "Pozor!: xml:lang atrib\u00fat {0} je v konflikte s {1} a s {2}"},
+	    { "helpset.unknownVersion",
+		  "Nezn\u00e1ma verzia {0}."},
+
+		// IndexView messages
+	    { "index.invalidIndexFormat",
+		  "Pozor!: Index m\u00e1 chybn\u00fd form\u00e1t"},
+	    { "index.unknownVersion",
+		  "Nezn\u00e1ma verzia {0}."},
+
+		// TOCView messages
+	    { "toc.wrongPublicID",
+		  "Nezn\u00e1me PublicID {0}"},
+	    { "toc.invalidTOCFormat",
+		  "Pozor!: TOC m\u00e1 chybn\u00fd form\u00e1t"},
+	    { "toc.unknownVersion",
+		  "Nezn\u00e1ma verzia {0}."},
+                  
+                //FavoritesView messages
+	    { "favorites.invalidFavoritesFormat",
+		  "Pozor!: Nespr\u00e1vny form\u00e1t s\u00faboru Favorites.xml"},
+	    { "favorites.unknownVersion",
+		  "Nespr\u00e1vna verzia {0}."},
+
+		// Map messages
+	    { "map.wrongPublicID",
+		  "Nezn\u00e1me PublicID {0}"},
+	    { "map.invalidMapFormat",
+		  "Pozor!: Map m\u00e1 nespr\u00e1vny form\u00e1t"},
+	    { "map.unknownVersion",
+		  "Nezn\u00e1ma verzia {0}."},
+
+	    // GUI components
+	    // Labels
+	   { "index.findLabel", "Vyh\u013Eada\u0165 : "},
+
+	    { "search.findLabel", "Vyh\u013Eada\u0165 : "},
+	    { "search.hitDesc", "Po\u010Det v\u00fdskytov v dokumente"},
+	    { "search.qualityDesc", "Miera nepresnosti" },
+	    { "search.high", "Najvy\u0161\u0161ia"},
+	    { "search.midhigh", "Vysok\u00e1"},
+	    { "search.mid", "Stredn\u00e1"},
+	    { "search.midlow", "N\u00edzka"},
+	    { "search.low", "Najni\u0161\u0161ia"},
+
+            { "favorites.add", "Pridaj"},
+            { "favorites.remove", "Zma\u017e"},
+            { "favorites.folder", "Zlo\u017eka"},
+            { "favorites.name", "N\u00e1zov"},
+            { "favorites.cut", "Vystrihni"},
+            { "favorites.paste", "Vlo\u017e"},
+            { "favorites.copy" ,"Kop\u00edruj" },
+
+            { "history.homePage", "Domovsk\u00e1 str\u00e1nka"},
+            { "history.unknownTitle", "<nezn\u00e1my titul str\u00e1nky>"},
+
+	    // ToolTips for Actions
+	    { "tooltip.BackAction", "Predch\u00e1dzaj\u00face"},
+	    { "tooltip.ForwardAction", "\u010Eal\u0161ie"},
+	    { "tooltip.PrintAction", "Tla\u010D"},
+	    { "tooltip.PrintSetupAction", "Nastavenie str\u00e1nky"},
+	    { "tooltip.ReloadAction", "Obnovi\u0165"},
+            { "tooltip.FavoritesAction", "Pridaj k ob\u013E\u00faben\u00fdm polo\u017Ek\u00e1m"},
+            { "tooltip.HomeAction", "Zobraz domovsk\u00fa str\u00e1nku"},
+
+	    // Accessibility names
+	    { "access.BackAction", "Spiatky"},
+	    { "access.ForwardAction", "Vpred"},
+	    { "access.HistoryAction", "Hist\u00f3ria"},
+	    { "access.PrintAction", "Tla\u010D"},
+	    { "access.PrintSetupAction", "Nastavenie Tla\u010De"},
+	    { "access.ReloadAction", "Obnovenie"},
+            { "access.HomeAction", "Domovsk\u00e1 Str\u00e1nka"},
+            { "access.FavoritesAction", "Pridaj k ob\u013E\u00faben\u00fdm polo\u017ek\u00e1m"},
+            { "access.contentViewer", "Prehliada\u010D obsahu"}
+
+	};
+    
+    }
+
+    
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/resources/Constants_zh.java b/jhMaster/JavaHelp/src/new/javax/help/resources/Constants_zh.java
new file mode 100644
index 0000000000000000000000000000000000000000..33c9ca85bfa7f8e7b30f75a2b5a6b883c449a965
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/resources/Constants_zh.java
@@ -0,0 +1,148 @@
+/*
+ * @(#)Constants_zh.java	1.6 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+/*
+ * @(#) Constants_zh.java 1.6 - last change made 10/30/06
+ */
+
+package javax.help.resources;
+
+import java.util.ListResourceBundle;
+
+/**
+ * Constants used for localizing JavaHelp.
+ *
+ * These are in the form of key, value.
+ * Translators take care to only translate the values.
+ */
+
+public class Constants_zh extends ListResourceBundle {
+    /**
+     * Overrides ListResourceBundle.
+     */
+    public Object[][] getContents() {
+        return new Object[][] {
+
+	    //  Constant strings and patterns
+	    { "helpset.wrongPublicID",
+		  "\u672a\u77e5\u7684 PublicID {0}"},
+	    { "helpset.wrongTitle",
+		  "\u8bd5\u56fe\u5c06\u6807\u9898\u8bbe\u7f6e\u4e3a {0}\uff0c\u4f46\u6807\u9898\u5df2\u8d4b\u503c\u4e3a {1}\u3002"},
+	    { "helpset.wrongHomeID",
+		  "\u8bd5\u56fe\u5c06 homeID \u8bbe\u7f6e\u4e3a {0} \u4f46 homeID \u5df2\u8d4b\u503c\u4e3a {1}\u3002"},
+	    { "helpset.subHelpSetTrouble",
+		  "\u521b\u5efa subhelpset \u65f6\u51fa\u9519\uff1a{0}\u3002"},
+	    { "helpset.malformedURL",
+		  "\u683c\u5f0f\u9519\u8bef\u7684 URL\uff1a{0}\u3002"},
+	    { "helpset.incorrectURL",
+		  "\u9519\u8bef\u7684 URL\uff1a{0}\u3002"},
+	    { "helpset.wrongText",
+		  "{0} \u4e0d\u80fd\u5305\u542b\u6587\u672c {1}\u3002"},
+	    { "helpset.wrongTopLevel",
+		  "{0} \u4e0d\u80fd\u4e3a\u9876\u7ea7\u6807\u8bb0\u3002"},
+	    { "helpset.wrongParent",
+		  "{0} \u7684\u7236\u6807\u8bb0\u4e0d\u80fd\u4e3a {1}\u3002"},
+	    { "helpset.unbalanced",
+		  "\u4e0d\u5747\u8861\u7684\u6807\u8bb0 {0}\u3002"},
+	    { "helpset.wrongLocale",
+		  "\u8b66\u544a\uff1axml:lang \u7279\u6027 {0} \u4e0e\u7f3a\u7701\u503c {1} \u53ca\u7f3a\u7701\u503c {2} \u51b2\u7a81\u3002"},
+	    { "helpset.unknownVersion",
+		  "\u672a\u77e5\u7248\u672c {0}\u3002"},
+
+		// IndexView messages
+	    { "index.invalidIndexFormat",
+		  "\u8b66\u544a\uff1a\u65e0\u6548\u7684\u7d22\u5f15\u683c\u5f0f"},
+	    { "index.unknownVersion",
+		  "\u672a\u77e5\u7248\u672c {0}\u3002"},
+
+		// TOCView messages
+	    { "toc.wrongPublicID",
+		  "\u672a\u77e5 PublicID {0}"},
+	    { "toc.invalidTOCFormat",
+		  "\u8b66\u544a\uff1a\u65e0\u6548\u7684\u76ee\u5f55\u683c\u5f0f"},
+	    { "toc.unknownVersion",
+		  "\u672a\u77e5\u7248\u672c {0}\u3002"},
+
+            // FavoritesView messages
+	    { "favorites.invalidFavoritesFormat",
+		  "Warning: Invalid Favorites format"},
+	    { "favorites.unknownVersion",
+		  "Unknown Version {0}."},
+
+		// Map messages
+	    { "map.wrongPublicID",
+		  "\u672a\u77e5 PublicID {0}"},
+	    { "map.invalidMapFormat",
+		  "\u8b66\u544a\uff1a\u65e0\u6548\u7684\u6620\u5c04\u683c\u5f0f"},
+	    { "map.unknownVersion",
+		  "\u672a\u77e5\u7248\u672c {0}\u3002"},
+
+	    // GUI components
+	    // Labels
+	    { "index.findLabel", "\u67e5\u627e\uff1a"},
+
+	    { "search.findLabel", "\u67e5\u627e\uff1a"},
+	    { "search.hitDesc", "\u6587\u6863\u4e2d\u51fa\u73b0\u7684\u6b21\u6570"},
+	    { "search.qualityDesc", "\u6587\u6863\u7684\u6700\u4f4e\u8865\u507f\u503c" },
+	    { "search.high", "\u9ad8"},
+	    { "search.midhigh", "\u8f83\u9ad8"},
+	    { "search.mid", "\u4e2d\u7b49"},
+	    { "search.midlow", "\u8f83\u4f4e"},
+	    { "search.low", "\u4f4e"},
+
+            { "favorites.add", "Add"},
+            { "favorites.remove", "Remove"},
+            { "favorites.folder", "New Folder"},
+            { "favorites.name", "Name"},
+            { "favorites.cut", "Cut"},
+            { "favorites.paste", "Paste"},
+            { "favorites.copy" , "Copy"},
+
+            { "history.homePage", "Home page"},
+            { "history.unknownTitle", "<unknown page title>"},
+
+	    // ToolTips for Action
+	    { "tooltip.BackAction", "\u4e0a\u4e00\u9875"},
+	    { "tooltip.NextAction", "\u4e0b\u4e00\u9875"},
+	    { "tooltip.PrintAction", "\u6253\u5370"},
+	    { "tooltip.PrintSetupAction", "\u9875\u8bbe\u7f6e"},
+	    { "tooltip.ReloadAction", "\u91cd\u65b0\u88c5\u8f7d"},
+            { "tooltip.HomeAction", "Go to home page"},
+
+	    // Accessibility names
+	    { "access.BackAction", "Previous Button"},
+	    { "access.ForwardAction", "Next Button"},
+	    { "access.HistoryAction", "History Button"},
+	    { "access.PrintAction", "Print Button"},
+	    { "access.PrintSetupAction", "Page Setup Button"},
+	    { "access.ReloadAction", "Reload Button"},
+            { "access.HomeAction", "Home Button"},
+            { "access.FavoritesAction", "Add to Favorites Button"},
+            { "access.contentViewer", "Content Viewer"}
+       };
+    }
+}
+
diff --git a/jhMaster/JavaHelp/src/new/javax/help/resources/package.html b/jhMaster/JavaHelp/src/new/javax/help/resources/package.html
new file mode 100644
index 0000000000000000000000000000000000000000..1033ce9e5372fdf0efdc547e377763b4a2d378a5
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/resources/package.html
@@ -0,0 +1,53 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<!--
+
+  @(#)package.html	1.2 99/03/19
+
+  Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+  DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+  This code is free software; you can redistribute it and/or modify it
+  under the terms of the GNU General Public License version 2 only, as
+  published by the Free Software Foundation.  Sun designates this
+  particular file as subject to the "Classpath" exception as provided
+  by Sun in the LICENSE file that accompanied this code.
+
+  This code is distributed in the hope that it will be useful, but WITHOUT
+  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+  version 2 for more details (a copy is included in the LICENSE file that
+  accompanied this code).
+
+  You should have received a copy of the GNU General Public License version
+  2 along with this work; if not, write to the Free Software Foundation,
+  Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+  Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+  CA 95054 USA or visit www.sun.com if you need additional information or
+  have any questions.
+
+-->
+
+</head>
+<body bgcolor="white">
+
+Supports localization of JavaHelp.
+The class <code>Constants</code> provides
+all the needed values.
+
+<!--
+<H2>Package Specification</H2>
+Link to updated API specification to be added here.
+-->
+
+<H2>Related Documentation</H2>
+
+<P>
+For overviews, tutorials, examples, guides, tool support,
+and other documentation,
+please see the <em>JavaHelp System User's Guide</em>.
+
+  </body>
+</html>
diff --git a/jhMaster/JavaHelp/src/new/javax/help/search/ConfigFile.java b/jhMaster/JavaHelp/src/new/javax/help/search/ConfigFile.java
new file mode 100644
index 0000000000000000000000000000000000000000..2a723264950ffd4cb7b659cd3329d1888734e220
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/search/ConfigFile.java
@@ -0,0 +1,200 @@
+/*
+ * @(#)ConfigFile.java	1.8 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @(#) ConfigFile.java 1.8 - last change made 10/30/06
+ */
+
+package javax.help.search;
+
+import java.io.*;
+import java.text.*;
+import java.util.Vector;
+import java.util.Hashtable;
+import java.util.Enumeration;
+
+/**
+ * Describes and parses the configuration file for
+ * the full-text search indexer.
+ *
+ * @see Indexer
+ * @version	1.8	10/30/06
+ * @author	Roger D. Brinkley
+ */
+
+public class ConfigFile {
+
+    private String remove;
+
+    private String prepend;
+
+    private Hashtable stopWords;
+
+    private String defStopWords[] = {
+	"a", "all", "am", "an", "and", "any", "are", "as", "at", "be", 	"but",
+	"by", "can", "could", "did", "do", "does", "etc", "for", "from",
+	"goes", "got", 	"had", "has", "have", "he", "her", "him", "his",
+	"how", "if", "in", "is", "it", "let", "me", "more", "much", "must",
+	"my", "nor", "not", "now", "of", "off", "on", "or", "our", "own",
+	"see", "set", "shall", "she", "should",  "so", "some", "than", "that",
+	"the", "them", "then", "there", "these", "this", "those", "though",
+	"to", "too", "us", "was", "way", "we", "what", "when", "where", 
+	"which", "who", "why", "will", "would", "yes", "yet", "you"};
+
+    private Vector files;
+
+    /**
+     * Creates a configuration file.
+     * @params configFile The config file.
+     * @params files A list of files to process in addition to any files in the config file.
+     * @params noStopWords If true do not allow stopwords, if false allow the stopwords
+     * defined in the config file or the default stop words.
+     */
+    public ConfigFile (String configFile, Vector files, boolean noStopWords) {
+	this.files = files;
+	LineNumberReader in;
+	String line;
+	String removeText = new String ("IndexRemove ");
+	String prependText = new String ("IndexPrepend ");
+	String fileText = new String ("File ");
+	String stopWordsText = new String ("StopWords ");
+	String stopWordsFileText = new String ("StopWordsFile ");
+	BreakIterator boundary;
+	int start;
+	String url;
+
+	stopWords = new Hashtable();
+
+	if (configFile == null) {
+	    if (!noStopWords) {
+		useDefaultStopWords();
+	    }
+	    return;
+	}
+	try {
+	    in = new LineNumberReader(new BufferedReader
+				      (new FileReader(configFile)));
+	    while ((line = in.readLine()) != null) {
+		if (line.startsWith(removeText)) {
+		    remove = line.substring (removeText.length(),
+					     line.length());
+		} else if (line.startsWith(prependText)) {
+		    prepend = line.substring (prependText.length(),
+					      line.length());
+		} else if (line.startsWith(fileText)) {
+		    String file = line.substring (fileText.length(),
+						  line.length());
+		    files.addElement(file);
+		} else if (line.startsWith(stopWordsFileText)) {
+		    String file = line.substring (stopWordsFileText.length(),
+						  line.length());
+		    addStopWordsFile(file);
+		} else if (line.startsWith(stopWordsText)) {
+		    if (noStopWords) {
+			continue;
+		    }
+		    String words = line.substring (stopWordsText.length(),
+						   line.length());
+		    boundary = BreakIterator.getWordInstance();
+		    boundary.setText(words);
+		    start = boundary.first();
+		    for (int end = boundary.next();
+			 end != BreakIterator.DONE;
+			 start = end, end = boundary.next()) {
+			String word = words.substring(start,end).trim().toLowerCase();
+			if (word.equals(",") || word.equals("")) {
+			    continue;
+			}
+			stopWords.put(word, word);
+		    }
+		} else {
+		    System.out.println ("Unknown Config Keyword at line " +
+					in.getLineNumber());
+		}
+	    }
+	    // If there aren't any stopwords then add the default stopwords
+	    if (stopWords.isEmpty() && !noStopWords) {
+		useDefaultStopWords();
+	    }
+	} catch (IOException e) {}
+    }
+
+    /**
+     * Returns the URL filename of a file in String format.
+     */
+    public String getURLString (String file) {
+	String url;
+
+	if (remove != null && (file.startsWith(remove))) {
+	    url = file.substring(remove.length(), file.length());
+	} else {
+	    url = file;
+	}
+	if (prepend != null) {
+	    url = prepend + url;
+	}
+	if (File.separatorChar != '/') {
+	    url = url.replace(File.separatorChar, '/');
+	}
+	return url;
+    }
+
+    /**
+     * Returns the list of stopwords from a config file.
+     */
+    public Enumeration getStopWords() { return stopWords.elements(); }
+
+    /**
+     * Gets the list of files from a config file.
+     */
+    public Vector getFiles () { return files; }
+
+    private void useDefaultStopWords() {
+	for (int i=0; i < defStopWords.length; i++) {
+	    stopWords.put(defStopWords[i], defStopWords[i]);
+	}
+    }
+
+    // Add stopwords from a file
+    // A single stop words exist per line in the file
+    private void addStopWordsFile(String swfile) {
+	String word;
+	LineNumberReader in;
+
+	if (swfile == null) {
+	    return;
+	}
+	try {
+	    in = new LineNumberReader(new BufferedReader
+				      (new FileReader(swfile)));
+	    while ((word = in.readLine()) != null) {
+		word = word.trim();
+		stopWords.put(word, word);
+	    }
+	} catch (IOException e) {}
+    }
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/search/IndexBuilder.java b/jhMaster/JavaHelp/src/new/javax/help/search/IndexBuilder.java
new file mode 100644
index 0000000000000000000000000000000000000000..13cdff52298e071ed5a891920ef505507ec668cd
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/search/IndexBuilder.java
@@ -0,0 +1,115 @@
+/*
+ * @(#)IndexBuilder.java	1.8 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @(#) IndexBuilder.java 1.8 - last change made 10/30/06
+ */
+
+package javax.help.search;
+
+import java.io.*;
+import java.util.Enumeration;
+
+/**
+ * Abstract base class that builds an index for a search database.
+ *
+ * @author Roger D. Brinkley
+ * @version	1.8	10/30/06
+ */
+
+public abstract class IndexBuilder
+{
+
+    protected String indexDir;
+
+    /**
+     * Builds an index at indexDir. If indexDir already exists
+     * the index is opened and the new doucments are merged into
+     * the existing document.
+     */
+    public IndexBuilder(String indexDir) throws Exception
+    {
+	debug("indexDir=" + indexDir);
+	this.indexDir = indexDir;
+	File test = new File(indexDir);	
+	try {
+	    if (!test.exists()) {
+		debug ("file " + indexDir + " didn't exist - creating");
+		test.mkdirs();
+	    }
+	} catch (java.lang.SecurityException e) {
+	}
+    }
+
+    /**
+     * Closes the index. 
+     */
+    public abstract void close() throws Exception;
+
+    /**
+     * Sets the stopwords in an index. If the stopwords are already 
+     * defined for an index, the stop words are merged with the existing
+     * set of stopwords.
+     * @params stopWords An Enumeration of Strings.
+     */
+    public abstract void storeStopWords(Enumeration stopWords);
+
+    /**
+     * Returns the list of stopwords for an index.
+     * @returns Enumeration An enumeration of Strings. Returns null if there are no stopwords.
+     */
+    public abstract Enumeration getStopWords();
+
+    /**
+     * Opens a document to store information.
+     */
+    public abstract void openDocument(String name) throws Exception;
+  
+    /**
+     * Closes the document. This prevents any additional information from being
+     * stored.
+     */
+    public abstract void closeDocument() throws Exception;
+
+    /**
+     * Stores a concept at a given position.
+     */
+    public abstract void storeLocation(String text, int position) throws Exception;
+    
+    /**
+     * Stores the title for the document.
+     */
+    public abstract void storeTitle(String title) throws Exception;
+
+    private boolean debug=false;
+    private void debug(String msg) {
+	if (debug) {
+	    System.err.println("IndexBuilder: "+msg);
+	}
+    }
+
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/search/IndexerKit.java b/jhMaster/JavaHelp/src/new/javax/help/search/IndexerKit.java
new file mode 100644
index 0000000000000000000000000000000000000000..5749860482cd1a77c272e1561552ec7f3ebf9635
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/search/IndexerKit.java
@@ -0,0 +1,181 @@
+/*
+ * @(#)IndexerKit.java	1.13 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @(#) IndexerKit.java 1.13 - last change made 10/30/06
+ */
+
+package javax.help.search;
+
+import java.io.*;
+import java.util.Locale;
+
+/**
+ * Establishes the requirements of an indexing object for a <em>type</em>
+ * of text content.  The DefaultKit acts as a factory for policy.  
+ * For example, an implementation 
+ * for HTML and RTF can be provided that is replaceable 
+ * with other implementations.
+ * <p>
+ * New kits are normally created by cloning a 
+ * prototype kit.  
+ *
+ * @author  Roger D. Brinkley
+ * @version %I	%G
+ */
+public abstract class IndexerKit implements Cloneable {
+
+    protected IndexBuilder builder;
+    protected ConfigFile config;
+    protected String file;
+    protected Locale locale;
+
+    /**
+     * Creates a copy of the indexer kit.  This
+     * allows an implementation to serve as a prototype
+     * for others, so that they can be quickly created.
+     *
+     * @return the copy
+     */
+    public abstract Object clone();
+
+    /**
+     * Gets the MIME type of the data that this
+     * kit represents support for.
+     *
+     * @return the type
+     */
+    public abstract String getContentType();
+
+    /**
+     * Sets the locale for string tokenizing. A null locale value is valid and means
+     * that no locale has been set for this IndexerKit.
+     */
+    public void setLocale (Locale locale) {
+	this.locale = locale;
+    }
+
+    /**
+     * Convenience method for setting the locale from a lang string
+     * Takes the lang string in the form of "language_country_variant".
+     * Parses the string and creates an appropriate locale.
+     * @param lang A string representation of a locale. If lang is null it is the
+     * same as setting the locale to null.
+     */
+    public void setLocale(String lang) {
+	if (lang == null) {
+	    setLocale((Locale)null);
+	    return;
+	}
+	String language;
+	String country;
+	String variant=null;
+	Locale newlocale;
+	int lpt = lang.indexOf("_");
+	if (lpt == -1) {
+	    language = lang;
+	    country = "";
+	    newlocale = new Locale(language, country);
+	} else {
+	    language = lang.substring(0, lpt);
+	    int cpt = lang.indexOf("_", lpt+1);
+	    if (cpt == -1) {
+		country = lang.substring(lpt+1);
+		newlocale = new Locale(language, country);
+	    } else {
+		country = lang.substring(lpt+1, cpt);
+		variant = lang.substring(cpt+1);
+		newlocale = new Locale(language, country, variant);
+	    }
+	}
+	setLocale(newlocale);
+    }
+
+    /**
+     * Gets the Locale. 
+     */
+    public Locale getLocale() {
+	return locale;
+    }
+
+    /**
+     * Parses content from the given stream. The stream is expected 
+     * to be in a format appropriate for this content
+     * handler to parse into tokens according to the locale of the class.
+     * In the absense of a locale, the default locale tokenizer
+     * is used.
+     * 
+     * @param in  The stream to read from.
+     * @param file The file name being parsed.
+     * @param builder The IndexBuilder for the full text insertion.
+     * @param config The indexer configuration information.
+     * @exception IOException on any I/O error.
+     */
+    public abstract void parse(Reader in, String file, boolean ignoreCharset,
+			       IndexBuilder builder,
+			       ConfigFile config) 
+	throws IOException;
+
+    /**
+     * Parses a string into tokens and stores the tokens.
+     */
+    public abstract int parseIntoTokens (String source, int pos);
+
+    /**
+     * Starts the storing of the dcoument.
+     */
+    protected abstract void startStoreDocument (String file) 
+	throws Exception;
+
+    /**
+     * Ends the storing of the document.
+     */
+    protected abstract void endStoreDocument () 
+	throws Exception;
+
+    /**
+     * Stores a token in the IndexBuilder.
+     */
+    protected abstract void storeToken (String token, int pos)
+	throws Exception;
+
+    /**
+     * Stores a title in the IndexBuilder.
+     */
+    protected abstract void storeTitle (String title) throws Exception;
+
+    /**
+     * Debug code
+     */
+
+    private boolean debugFlag=false;
+    private void debug(String msg) {
+        if (debugFlag) {
+            System.err.println("IndexerKit: "+msg);
+        }
+    }
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/search/MergingSearchEngine.java b/jhMaster/JavaHelp/src/new/javax/help/search/MergingSearchEngine.java
new file mode 100644
index 0000000000000000000000000000000000000000..3c4b684fb9b14f64194493c7d0db285a22dd8df8
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/search/MergingSearchEngine.java
@@ -0,0 +1,350 @@
+/*
+ * @(#)MergingSearchEngine.java	1.8 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help.search;
+
+import java.util.Hashtable;
+import java.util.Vector;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.net.URL;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import javax.help.HelpSet;
+import javax.help.HelpUtilities;
+import javax.help.NavigatorView;
+import javax.help.search.SearchListener;
+import javax.help.search.SearchEvent;
+import javax.help.search.SearchEngine;
+import javax.help.search.SearchQuery;
+
+/*
+ * A class that provides a merging/removing layer for the search.
+ */
+public class MergingSearchEngine extends SearchEngine {
+    
+    private Vector engines;
+    private Hashtable enginePerView = new Hashtable();
+    private boolean stopQuery = false;
+
+    public MergingSearchEngine(NavigatorView view) {
+	if (view == null) {
+	    throw new IllegalArgumentException("view must not be null");
+	}
+	engines = new Vector();
+	// HERE - the makeEngine() should be delayed until the actual query
+	SearchEngine engine = makeEngine(view);
+	engines.addElement(engine);
+    }
+	
+    public MergingSearchEngine(SearchEngine engine) {
+	if (engine == null) {
+	    throw new IllegalArgumentException("engine must not be null");
+	}
+	engines = new Vector();
+	engines.addElement(engine);
+    }
+
+    /**
+     * Creates the query for this helpset.
+     */
+    public SearchQuery createQuery() {
+	return new MergingSearchQuery(this);
+    }
+
+    /**
+     * Adds/Removes a Search Engine to/from list.
+     *
+     * Possibly the makeEngine should be delayed until the actual query.
+     */
+
+    public void merge(NavigatorView view) {
+	if (view == null) {
+	    throw new IllegalArgumentException("view must not be null");
+	}
+	SearchEngine engine = makeEngine(view);
+	if (engine == null) {
+	    throw new IllegalArgumentException("view is invalid");
+	}
+	engines.addElement(engine);
+	enginePerView.put(view, engine);
+    }
+
+    /*
+     * Remove a Navigator View
+     * Throws an IllegalArgumentException if view is null or if there
+     * is no search engine for a view.
+     */
+    public void remove(NavigatorView view) {
+	if (view == null) {
+	    throw new IllegalArgumentException("view is either null or invalid");
+	}
+	SearchEngine engine = (SearchEngine) enginePerView.get(view);
+	if (engine != null) {
+	    engines.removeElement(engine);
+	    enginePerView.remove(engine);
+	} else {
+	    throw new IllegalArgumentException("view is either null or invalid");
+	}
+
+    }
+
+    public Enumeration getEngines() {
+	return engines.elements();
+    }
+
+    private SearchEngine makeEngine(NavigatorView view) {
+	Hashtable params = view.getParameters();
+
+	// if there were no parameters or there were parameters but
+	// no data then return a null SearchEngine
+	if (params == null || 
+	    (params != null && !params.containsKey("data"))) {
+	    return null;
+	}
+	String engineName = (String) params.get("engine");
+	HelpSet hs = view.getHelpSet();
+	URL base = hs.getHelpSetURL();
+	ClassLoader loader = hs.getLoader();
+
+	if (engineName == null) {
+	    engineName = HelpUtilities.getDefaultQueryEngine();
+	    params.put("engine", engineName);
+	}
+	
+	SearchEngine back = null;
+
+	Constructor konstructor;
+	Class types[] = {URL.class, Hashtable.class};
+	Object args[] = {base, params};
+	Class klass;
+
+	debug("makeEngine");
+	debug("  base: "+base);
+	debug("  params: "+params);
+
+	try {
+	    if (loader == null) {
+		klass = Class.forName(engineName);
+	    } else {
+		klass = loader.loadClass(engineName);
+	    }
+	} catch (Throwable t) {
+	    throw new Error("Could not load engine named "+engineName+" for view: "+view);
+	}
+
+	try {
+	    konstructor = klass.getConstructor(types);
+	} catch (Throwable t) {
+	    throw new Error("Could not find constructor for "+engineName+". For view: "+view);
+	}
+	try {
+	    back = (SearchEngine) konstructor.newInstance(args);
+	} catch (InvocationTargetException e) {
+            System.err.println("Exception while creating engine named "+engineName+" for view: "+view);
+            e.printStackTrace();
+	} catch (Throwable t) {
+	    throw new Error("Could not create engine named "+engineName+" for view: "+view);
+	}
+	return back;
+    }
+
+    private class MergingSearchQuery extends SearchQuery implements SearchListener {
+
+	private MergingSearchEngine mhs;
+	private Vector queries;
+	private String searchparams;
+
+	public MergingSearchQuery(SearchEngine hs) {
+	    super(hs);
+	    if (hs instanceof MergingSearchEngine) {
+		this.mhs = (MergingSearchEngine) hs;
+	    }
+	}
+
+	// Start all the search engines
+	public synchronized void start(String searchparams, Locale l)
+	    throws IllegalArgumentException, IllegalStateException
+	{
+	    MergingSearchEngine.this.debug("startSearch()");
+
+	    // if we're already alive you can't start again
+	    if (isActive()) {
+		throw new IllegalStateException();
+	    }
+
+	    stopQuery = false;
+
+	    // setup everthing to get started
+	    super.start(searchparams, l);
+	    queries = new Vector();
+		
+		// Get a query for each engine
+	    for (Enumeration e = mhs.getEngines();
+		 e.hasMoreElements(); ) {
+		SearchEngine engine = (SearchEngine) e.nextElement();
+		if (engine != null) {
+		    queries.addElement(engine.createQuery());
+		}
+	    }
+		
+	    // Set the listener to this class and start the query
+	    for (Enumeration e = queries.elements(); e.hasMoreElements(); ) {
+		SearchQuery query = (SearchQuery) e.nextElement();
+		query.addSearchListener(this);
+		query.start(searchparams, l);
+	    }
+	}
+
+	// Stop all the search engines
+	// This is an override of the SearchQuery.stop
+	// Donnot call super.stop in this method as an
+	// extra fireSearchStopped will be genertated
+	public synchronized void stop() throws IllegalStateException {
+	    // Can't stop what is already stopped silly
+	    if (queries == null) {
+		return;
+	    }
+
+	    stopQuery = true;
+
+	    // Loop through all the queries and and make sure they have
+	    // all inActive. If any query is active wait a small period of
+	    // time 
+	    boolean queriesActive = true;
+	    while (queriesActive) {
+		queriesActive = false;
+
+		// Throughout this process the queries will disappear so
+		// protect against a null pointer
+		if (queries == null) {
+		    continue;
+		}
+		for (Enumeration e = queries.elements();
+		     e.hasMoreElements(); ) {
+		    SearchQuery query = (SearchQuery) e.nextElement();
+		    if (query.isActive()) {
+			debug ("queries are active waiting to stop");
+			queriesActive = true;
+		    }
+		}
+		if (queriesActive) {
+		    try {
+			wait(250);
+		    } catch (InterruptedException ex) {
+			ex.printStackTrace();
+		    }
+		}
+	    }
+
+	    queries = null;
+	}
+
+	public boolean isActive() {
+
+	    // if there aren't any queries we aren't alive
+	    if (queries == null) {
+		return false;
+	    }
+
+	    // Loop through all the queries and see if anyone is alive
+	    for (Enumeration e = queries.elements();
+		 e.hasMoreElements(); ) {
+		SearchQuery query = (SearchQuery) e.nextElement();
+		if (query.isActive()) {
+		    return true;
+		}
+	    }
+
+	    // Didn't find anyone alive so we're not alive
+	    return false;
+	}
+
+	public SearchEngine getSearchEngine() {
+	    return mhs;
+	}
+
+	public synchronized void itemsFound(SearchEvent e) {
+	    SearchQuery queryin = (SearchQuery) e.getSource();
+
+	    if (stopQuery) {
+		return;
+	    }
+
+	    // Loop through all the queries and match this one
+	    if (queries != null) {
+		Enumeration enum1 = queries.elements();
+		while (enum1.hasMoreElements()) {
+		    SearchQuery query = (SearchQuery) enum1.nextElement();
+		    if (query == queryin) {
+			// Redirect any Events as if they were from me
+			fireItemsFound(e);
+		    }
+		}
+	    }
+	}
+
+	public void searchStarted(SearchEvent e) {
+	    // Ignore these events as this class already informed
+	    // the listeners the search was started so we don't have 
+	    // to do anything else
+	}
+
+	public synchronized void searchFinished(SearchEvent e) {
+	    SearchQuery queryin = (SearchQuery) e.getSource();
+		
+	    // Loop through all the queries and match this one
+	    if (queries != null) {
+		Enumeration enum1 = queries.elements();
+		while (enum1.hasMoreElements()) {
+		    SearchQuery query = (SearchQuery) enum1.nextElement();
+		    if (query == queryin) {
+			queryin.removeSearchListener(this);
+			queries.removeElement(query);
+		    }
+		}
+		// If all the queries are done then send a searchFinished
+		if (queries.isEmpty()) {
+		    queries = null;
+		    if (!stopQuery) {
+			fireSearchFinished();
+		    }
+		}
+	    }
+		
+	}
+
+    }    // This needs to be public to deal with inner classes...
+
+    private static final boolean debug = false;
+    private static void debug(String msg) {
+	if (debug) {
+	    System.err.println("MergineSearchEngine: "+msg);
+	}
+    }
+
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/search/SearchEngine.java b/jhMaster/JavaHelp/src/new/javax/help/search/SearchEngine.java
new file mode 100644
index 0000000000000000000000000000000000000000..98b86e6ff5467ac2fceedd4880541f89ce1db22b
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/search/SearchEngine.java
@@ -0,0 +1,95 @@
+/*
+ * @(#)SearchEngine.java	1.8 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help.search;
+
+import javax.help.event.EventListenerList;
+import javax.help.search.SearchEvent;
+import javax.help.search.SearchListener;
+import java.net.URL;
+import java.util.Hashtable;
+import java.util.Vector;
+import java.util.Locale;
+import java.security.InvalidParameterException;
+
+/**
+ * Defines the methods used to access a search engine.
+ * Each instance is created by a engine factory.
+ * 
+ * Extensions of SearchEngine can perform the search or negotiate the search
+ * results with an outside agent. A server search engine is an an example
+ * of an outside agent.
+ *
+ * Search results are returned through SearchEvents to listeners that
+ * register with a SearchQuery instance. The SearchQuery
+ * is returned from the method createQuery.
+ *
+ * @author Roger D. Brinkley
+ * @version	1.6	03/19/99
+ *
+ * @see javax.help.search.SearchEvent
+ * @see javax.help.search.SearchListener
+ */
+
+public abstract class SearchEngine {
+
+    protected URL base;		// the base for resolving URLs against
+    protected Hashtable params;	// other parameters to the engine
+
+    /**
+     * Creates a SearchEngine using the standard JavaHelp SearchEngine
+     * parameters. Only this constructor is used to create a SearchEngine
+     * from within a search view.
+     *
+     * @param base The base address of the data.
+     * @param params A hashtable of parameters from the search view.
+     */
+    public SearchEngine(URL base, Hashtable params) 
+	throws InvalidParameterException
+    {
+	this.base = base;
+	this.params = params;
+    }
+
+    /**
+     * Creates a SearchEngine.
+     */
+    public SearchEngine() {
+    }
+
+    /**
+     * Creates a new search query.
+     */
+    public abstract SearchQuery createQuery() throws IllegalStateException;
+
+    private static final boolean debug = false;
+    private static void debug(String msg) {
+	if (debug) {
+	    System.err.println("SearchEngine: "+msg);
+	}
+    }
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/search/SearchEvent.java b/jhMaster/JavaHelp/src/new/javax/help/search/SearchEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..80c00edd84e0aa40886eab1280b1267c1acc57b8
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/search/SearchEvent.java
@@ -0,0 +1,116 @@
+/*
+ * @(#)SearchEvent.java	1.22 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help.search;
+
+import java.util.Vector;
+import java.util.Enumeration;
+
+/**
+ * Encapsulates information that describes changes to a SearchQuery.  It is used
+ * to notify listeners of the change.
+ *
+ * @author Roger D. Brinkley
+ * @version	1.16	03/19/99
+ */
+
+public class SearchEvent extends java.util.EventObject
+{
+    private String params;
+    private boolean searching;
+    private Vector items;
+
+    /**
+     * Represents a change in the SearchEngine. Used for starting the search
+     * or ending the search.
+     *
+     * @param source The source of this event.
+     * @param params The search parameters.
+     * @param searching A boolean operator that indicates if searching is 
+     * executing (true) or stopped (false).
+     * @throws IllegalArgumentException if source, or params is NULL.
+     */
+    public SearchEvent(Object source, String params, boolean searching) {
+	super (source);
+	if (params == null) {
+	    throw new IllegalArgumentException("null params");
+	}
+	this.params = params;
+	this.searching = searching;
+    }
+
+    /**
+     * Represents a change in the SearchEngine. Used to indicate that either a single
+     * item or a group of items have matched the params.
+     *
+     * @param source The source of this event.
+     * @param params The search parameters.
+     * @param searching A boolean operator that indicates if a search is 
+     * executing (true) or stopped (false).
+     * @param items A Vector of SearchItems matching the the search params.
+     *
+     * @throws IllegalArgumentException if source, params, or items is NULL.
+     * @see java.javahelp.SearchItems
+     */
+    public SearchEvent(Object source, String params, boolean searching, Vector items) {
+	super(source);
+	if (params == null) {
+	    throw new IllegalArgumentException("null params");
+	}
+	this.params = params;
+	this.searching = searching;
+	if (items == null) {
+	    throw new IllegalArgumentException("null items");
+	}
+	this.items = items;
+    }
+
+
+    /**
+     * Returns the parameters to the query.
+     */
+    public String getParams() {
+	return params;
+    }
+
+    /**
+     * A boolean value that indicates if the search is completed.
+     */
+    public boolean isSearchCompleted() {
+	return searching;
+    }
+
+    /**
+     * An enumerated list of SearchItems that match parameters of the query.
+     */
+    public Enumeration getSearchItems() {
+	if (items == null) {
+	    return null;
+	}
+	return items.elements();
+    }
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/search/SearchItem.java b/jhMaster/JavaHelp/src/new/javax/help/search/SearchItem.java
new file mode 100644
index 0000000000000000000000000000000000000000..aef5e667a7942f4d5408a5821901822705011af0
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/search/SearchItem.java
@@ -0,0 +1,190 @@
+/*
+ * @(#)SearchItem.java	1.21 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help.search;
+
+import java.util.Vector;
+import java.util.Enumeration;
+import java.net.URL;
+
+/**
+ * A SearchItem corresponds to one specific item found in a search query.
+ * SearchItems are used in the default Search navigator.
+ * 
+ * @see javax.help.SearchTOCItem
+ * @see javax.help.search.SearchEvent
+ * @see javax.help.search.SearchListener
+ *
+ * @author Roger D. Brinkley
+ * @version	1.21	10/30/06
+ */
+
+public class SearchItem { 
+    private URL base;
+    private String title;
+    private String lang;
+    private String filename;
+    private double confidence; 
+    private int begin;
+    private int end;
+    private Vector concepts;
+
+    /**
+     * Constructs a SearchItem
+     *
+     * @param base The URL to the base from which file is a spec.
+     * @param title Title of the item
+     * @param lang A string representation of the locale. A null lang is valid
+     * and represents the default locale.
+     * @param filename FileName for the item.
+     * @param confidence How closely this matches the params.
+     * @param begin Starting position where the (requested) match has been found.
+     * @param end Ending position.
+     * @param concepts A vector of concepts.
+     */
+    public SearchItem(URL base,
+		      String title, String lang, String filename,
+		      double confidence,
+		      int begin, int end, Vector concepts) {
+	if (base == null) {
+	    throw new NullPointerException("base");
+	}
+	this.base = base;
+	if (title == null) {
+	    throw new NullPointerException("title");
+	}
+	this.title = title;
+	this.lang = lang;
+	if (filename == null) {
+	    throw new NullPointerException("fileName");
+	}
+	this.filename = filename;
+	this.confidence = confidence;
+	this.begin = begin;
+	this.end = end;
+	if (concepts == null) {
+	    throw new NullPointerException("concepts");
+	}
+	this.concepts = concepts;
+    }
+
+    /**
+     * Gets the base of the SearchItem.
+     *
+     * @return The base for this SearchItem.  Should be used with filename to
+     * 	obtain a URL to the desired hit.
+     */
+    public URL getBase() {
+	return base;
+    }
+
+    /**
+     * Gets the title of the SearchItem.
+     *
+     * @return The title of the document.  Used to present the hit in the navigator.
+     */
+    public String getTitle() {
+	return title;
+    }
+
+    /**
+     * Gets the lang of the SearchItem.
+     *
+     * @return The title of the document.  Used to present the hit in the navigator.
+     */
+    public String getLang() {
+	return lang;
+    }
+
+    /**
+     * Gets the spec (as a URL relative to getBase() ) to the document.
+     *
+     * @return The spec, relative to getBase(), to the document containing the hit.
+     */
+    public String getFilename() {
+	return filename;
+    }
+    
+    /**
+     * Gets the confidence value for the hit.
+     *
+     * @return The confidence value for the hit.  
+     * This measures how "good" the hit is. The lower the value the better.
+     */
+    public double getConfidence() {
+	return confidence;
+    }
+
+    /**
+     * Gets the begin pointer position for the hit.
+     *
+     * @return The starting position for the area in the document where a hit is found.
+     */
+    public int getBegin() {
+	return begin;
+    }
+
+    /**
+     * Gets the ending pointer position.
+     * 
+     * @return The ending position for the area in the document where a hit is found.
+     */
+    public int getEnd() {
+	return end;
+    }
+
+    /**
+     * If there are "concepts" against which the query is made, this is an enumeration
+     * of the concepts.  Otherwise null.
+     *
+     * @return An enumeration of the concepts found in this query.
+     */
+    public Enumeration getConcepts() {
+	return concepts.elements();
+    }
+
+    public String toString() {
+	StringBuffer result;
+	result = new StringBuffer(confidence + " " + title + ":" + 
+				  base + filename + " [" + begin + "," + end + 
+				  "], {");
+	if (concepts == null) {
+	    result.append("}");
+	    return result.toString();
+	}
+	Enumeration enum1 = concepts.elements();
+	while(enum1.hasMoreElements()) {
+	    String concept = (String)enum1.nextElement();
+	    result.append(concept);
+	    if (enum1.hasMoreElements()) {
+		result.append(",");
+	    }
+	}
+	result.append("}");
+	return result.toString();
+    }
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/search/SearchListener.java b/jhMaster/JavaHelp/src/new/javax/help/search/SearchListener.java
new file mode 100644
index 0000000000000000000000000000000000000000..5baf297e2064ea5cb9e9eefb0f9e1560eb50e1b1
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/search/SearchListener.java
@@ -0,0 +1,56 @@
+/*
+ * @(#)SearchListener.java	1.11 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help.search;
+
+/**
+ * Defines the interface for an object that listens to
+ * changes from a SearchQuery instance.
+ *
+ * @author Roger D. Brinkley
+ * @version	1.11	10/30/06
+ */
+
+public interface SearchListener extends java.util.EventListener
+{
+    /**
+     * Tells the listener that matching SearchItems have been found.
+     */
+    void itemsFound(SearchEvent e);
+
+    /**
+     * Tells the listener that the search has started.
+     */
+    void searchStarted(SearchEvent e);
+
+
+    /**
+     * Tells the listener that the search has finished
+     */
+    void searchFinished(SearchEvent e);
+}
+
diff --git a/jhMaster/JavaHelp/src/new/javax/help/search/SearchQuery.java b/jhMaster/JavaHelp/src/new/javax/help/search/SearchQuery.java
new file mode 100644
index 0000000000000000000000000000000000000000..273150b72cefb80a526b413ea3f981ece621efbe
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/search/SearchQuery.java
@@ -0,0 +1,247 @@
+/*
+ * @(#)SearchQuery.java	1.9 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help.search;
+
+import javax.help.event.EventListenerList;
+import javax.help.search.SearchEvent;
+import javax.help.search.SearchListener;
+import java.net.URL;
+import java.util.Vector;
+import java.util.Locale;
+import java.util.Enumeration;
+
+/**
+ * The instance of a query on a search database. It is 
+ * instantiated by SearchEngine.startQuery.
+ *
+ * Subclasses of SearchQuery can perform the search or negotiate the search
+ * results with an outside agent as setup in the SearchEngine class. A server
+ * search engine is an an example of an outside agent. 
+ *
+ * Search results are returned through SearchEvents to listeners that
+ * register with a SearchEngine instance.
+ *
+ * @author Roger D. Brinkley
+ * @version	1.22	09/16/98
+ *
+ * @see javax.help.search.SearchEvent
+ * @see javax.help.search.SearchListener
+ */
+
+public abstract class SearchQuery {
+
+    protected EventListenerList listenerList = new EventListenerList();
+    protected SearchEngine hs;
+    protected String searchparams;
+    protected Locale l;
+
+    /**
+     * Creates a SearchQuery.
+     */
+    public SearchQuery(SearchEngine hs) {
+	this.hs = hs;
+    }
+
+    /**
+     * Adds a listener for the SearchEngine posted after the search has
+     * started, stopped, or search parameters have been defined.
+     * 
+     * @param l The listener to add.
+     * @see java.javahelp.SearchEngine#removeSearchListener
+     */
+    public void addSearchListener(SearchListener l) {
+	listenerList.add(SearchListener.class, l);
+    }
+
+    /**
+     * Removes a listener previously added with <tt>addSearchListener</tt>.
+     *
+     * @param l The listener to remove.
+     * @see java.javahelp.SearchEngine#addSearchListener
+     */
+    public void removeSearchListener(SearchListener l) {
+	listenerList.remove(SearchListener.class, l);
+    }
+
+    /**
+     * Starts the search. This method invokes searchStarted on 
+     * SearchListeners and stores the searchparams. Extensions
+     * of SearchQuery should fully implement this method according
+     * to the needs of the SearchQuery and its corresponding SearchEngine.
+     * 
+     *
+     * @param searchparams The search string.
+     * @param locale The locale of the search string.
+     * @exception IllegalArgumentException The parameters are not 
+     * understood by this engine.
+     * @exception IllegalStateException There is an active search in 
+     * progress in this instance.
+     */
+    public void start(String searchparams, Locale l)
+	throws IllegalArgumentException, IllegalStateException
+    {
+	this.searchparams = searchparams;
+	this.l = l;
+	fireSearchStarted();
+    }
+
+    /**
+     * Stops the search. This method invokes searchStopped on 
+     * SearchListeners. Extensions of 
+     * SearchQuery should fully implement this method according to needs
+     * of the SearchQuery and its corresponding SearchEngine. 
+     *
+     * @exception IllegalStateException The search engine is not in a state in which it can be started.
+     */
+    public void stop() throws IllegalStateException {
+	fireSearchFinished();
+    }
+
+    /**
+     * Returns the SearchEngine associated with this SearchQuery.
+     */
+    public SearchEngine getSearchEngine() {
+	return hs;
+    }
+
+    /**
+     * Determines if this SearchQuery is active.
+     *
+     * @returns True if active, false otherwise
+     */
+    public abstract boolean isActive();
+
+    /**
+     * Notifies that query of items is found in the search.
+     *
+     * @param docs A vector of SearchItem.
+     * @param inSearch Is the search completed?
+     */
+    public void itemsFound(boolean inSearch, Vector docs) {
+	fireItemsFound(inSearch, docs);
+    }
+
+    /**
+     * Notifies that a SearchItem has been found.
+     *
+     * @param params The parameters to the search.
+     * @param inSearch Is the search completed?
+     * @param docs A vector of SearchItem.
+     * @see javax.help.search.SearchItem
+     */
+    protected void fireItemsFound(boolean inSearch, Vector docs) {
+	debug("fireItemsFound");
+	debug("  params: " + searchparams);
+	debug("  insearch: " + inSearch);
+	debug("  docs: " + docs);
+	Object[] listeners = listenerList.getListenerList();
+	SearchEvent e = null;
+
+	for (int i = listeners.length - 2; i >= 0; i -= 2) {
+	    if (listeners[i] == SearchListener.class) {
+		if (e == null) {
+		    e = new SearchEvent(this, searchparams,
+					    inSearch, docs);
+		}
+		((SearchListener)listeners[i+1]).itemsFound(e);
+	    }	       
+	}
+    }
+
+    /**
+     * Passs through that a SearchEvent has happened.
+     * This is useful for SearchEngine engines that encapsulate others.
+     *
+     * @param e The SearchEvent to pass through.
+     */
+    protected void fireItemsFound(SearchEvent e) {
+	Object[] listeners = listenerList.getListenerList();
+
+	Vector newItems = new Vector();
+	for (Enumeration enum1 = e.getSearchItems();
+	     enum1.hasMoreElements(); ) {
+	    newItems.addElement((SearchItem) enum1.nextElement());
+	}
+
+	SearchEvent e2 = new SearchEvent(this, e.getParams(), 
+						 e.isSearchCompleted(),
+						 newItems);
+	for (int i = listeners.length - 2; i >= 0; i -= 2) {
+	    if (listeners[i] == SearchListener.class) {
+		((SearchListener)listeners[i+1]).itemsFound(e2);
+	    }	       
+	}
+    }
+
+    /**
+     * Notifies that a search has started.
+     *
+     * @param params The parameters to the search.
+     */
+    protected void fireSearchStarted() {
+	debug("fireSearchStarted");
+	Object[] listeners = listenerList.getListenerList();
+	SearchEvent e = null;
+
+	for (int i = listeners.length - 2; i >= 0; i -= 2) {
+	    if (listeners[i] == SearchListener.class) {
+		if (e == null) {
+		    e = new SearchEvent(this, searchparams, true);
+		}
+		((SearchListener)listeners[i+1]).searchStarted(e);
+	    }	       
+	}
+    }
+
+    /**
+     * Notifies that a search has completed.
+     *
+     * @param params The parameters to the search.
+     */
+    protected void fireSearchFinished() {
+	debug("fireSearchFinished");
+	Object[] listeners = listenerList.getListenerList();
+	SearchEvent e = null;
+
+	for (int i = listeners.length - 2; i >= 0; i -= 2) {
+	    if (listeners[i] == SearchListener.class) {
+		if (e == null) {
+		    e = new SearchEvent(this, searchparams, false);
+		}
+		((SearchListener)listeners[i+1]).searchFinished(e);
+	    }	       
+	}
+    }
+    
+    private static final boolean debug = false;
+    private static void debug(String msg) {
+	if (debug) {
+	    System.err.println("SearchQuery: "+msg);
+	}
+    }
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/search/package.html b/jhMaster/JavaHelp/src/new/javax/help/search/package.html
new file mode 100644
index 0000000000000000000000000000000000000000..5040eefbee21c8b10b5fda1bd17ce2e7cbfff51a
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/search/package.html
@@ -0,0 +1,75 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<!--
+
+  @(#)package.html	1.3 99/04/07
+
+  Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+  DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+  This code is free software; you can redistribute it and/or modify it
+  under the terms of the GNU General Public License version 2 only, as
+  published by the Free Software Foundation.  Sun designates this
+  particular file as subject to the "Classpath" exception as provided
+  by Sun in the LICENSE file that accompanied this code.
+
+  This code is distributed in the hope that it will be useful, but WITHOUT
+  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+  version 2 for more details (a copy is included in the LICENSE file that
+  accompanied this code).
+
+  You should have received a copy of the GNU General Public License version
+  2 along with this work; if not, write to the Free Software Foundation,
+  Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+  Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+  CA 95054 USA or visit www.sun.com if you need additional information or
+  have any questions.
+
+-->
+
+</head>
+<body bgcolor="white">
+
+Supports simple access to search engines.  JavaHelp supports a
+standard full-text search view and navigator.  The view interacts
+with a search engine through this package.  The reference
+implementation provides a search engine that implements these
+interfaces, but others can also be used--the specific search engine
+is part of the information specified in the search view.  This separation
+provides full-text search functionality while not imposing specific
+formats.  These details are encapsulated in a search engine type.
+
+<p>
+<code>HelpSearch</code> is an abstract base class for the search
+engines, <code>SearchQuery</code> obtained from it can be used to
+perform the actual queries.  Individual items found by a search are
+<code>SearchItem</code>s which can be fired as
+<code>HelpEvent</code>s.
+
+<p>
+The creation of search databases is done by subclasses of the
+abstract class <code>IndexBuilder</code> based on the MIME type of
+each document being indexed.  Details of the index building process
+can be given through instances of <code>ConfigFile</code>.
+
+<p>
+<em>Note:</em> Registration of IndexerKits should probably be visible
+in this package.
+
+<!--
+<H2>Package Specification</H2>
+Link to updated API specification to be added here.
+-->
+
+<H2>Related Documentation</H2>
+
+<P>
+For overviews, tutorials, examples, guides, tool support,
+and other documentation,
+please see the <em>JavaHelp System User's Guide</em>.
+
+  </body>
+</html>
diff --git a/jhMaster/JavaHelp/src/new/javax/help/tagext/IndexItemTEI.java b/jhMaster/JavaHelp/src/new/javax/help/tagext/IndexItemTEI.java
new file mode 100644
index 0000000000000000000000000000000000000000..78f5e7e180fbf472636d6249b719a2b175a9261d
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/tagext/IndexItemTEI.java
@@ -0,0 +1,66 @@
+/*
+ * @(#)IndexItemTEI.java	1.2 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help.tagext;
+
+import javax.servlet.jsp.tagext.*;
+
+/**
+ * The JSP tag extra info class for an IndexItem
+ *
+ * @author Roger D. Brinkley
+ * @version	1.2	10/30/06
+ * @see javax.help.IndexItem
+ */
+
+public class IndexItemTEI extends TagExtraInfo {
+  
+   public IndexItemTEI() {
+      super();
+   }
+
+   public VariableInfo[] getVariableInfo(TagData data) {
+       return new VariableInfo[] {
+	   new VariableInfo("name", "java.lang.String", true, 
+			    VariableInfo.NESTED),
+	   new VariableInfo("helpID", "java.lang.String", true, 
+			    VariableInfo.NESTED),
+	   new VariableInfo("parent", "java.lang.String", true, 
+			    VariableInfo.NESTED),
+	   new VariableInfo("parentID", "java.lang.String", true, 
+			    VariableInfo.NESTED),
+	   new VariableInfo("node", "java.lang.String", true, 
+			    VariableInfo.NESTED),
+	   new VariableInfo("nodeID", "java.lang.String", true, 
+			    VariableInfo.NESTED),
+	   new VariableInfo("contentURL", "java.lang.String", true, 
+			    VariableInfo.NESTED),
+	   new VariableInfo("expansionType", "java.lang.String", true, 
+			    VariableInfo.NESTED)
+       };
+   }
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/tagext/IndexItemTag.java b/jhMaster/JavaHelp/src/new/javax/help/tagext/IndexItemTag.java
new file mode 100644
index 0000000000000000000000000000000000000000..420744ed835f58c328eab84e7ace21aa4790aeb4
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/tagext/IndexItemTag.java
@@ -0,0 +1,217 @@
+/*
+ * @(#)IndexItemTag.java	1.4 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help.tagext;
+
+import javax.servlet.jsp.*;
+import javax.servlet.jsp.tagext.*;
+import java.util.*;
+import java.io.*;
+import java.net.URL;
+import java.net.MalformedURLException;
+import javax.help.HelpBroker;
+import javax.help.HelpSet;
+import javax.help.Map;
+import javax.help.Map.ID;
+import javax.help.Merge;
+import javax.help.MergeHelpUtilities;
+import javax.help.NavigatorView;
+import javax.help.IndexItem;
+import javax.help.IndexView;
+import javax.help.SortMerge;
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.TreeNode;
+
+/**
+ * The JSP tag class for an IndexItem
+ *
+ * @author Roger D. Brinkley
+ * @version	1.4	10/30/06
+ * @see javax.help.IndexItem
+ */
+
+public class IndexItemTag extends BodyTagSupport {
+    private Enumeration treeEnum;
+    private DefaultMutableTreeNode topNode;
+    private String baseID="root";
+    private HelpBroker hb;
+    private IndexView view=null;
+
+    public void setIndexView(IndexView view) {
+	this.view = view;
+    }
+
+    public void setBaseID(String baseID) {
+	this.baseID = baseID;
+    }
+
+    public void setHelpBroker(HelpBroker hb) {
+	this.hb = hb;
+    }
+
+    private void initialize() {
+	if (view == null) {
+	    return;
+	}
+	topNode = view.getDataAsTree();
+	treeEnum = topNode.preorderEnumeration();
+
+	String mergeType = view.getMergeType();
+	HelpSet hs = view.getHelpSet();
+        Locale locale = hs.getLocale();
+
+
+	// Make sure the children are all handled correctly
+	MergeHelpUtilities.mergeNodeChildren(mergeType, topNode);
+        
+	// add all the subhelpsets
+        addSubHelpSets(hs);
+    }
+
+    /** Adds subhelpsets
+     *
+     * @param hs The HelpSet which subhelpsets will be added
+     */
+    private void addSubHelpSets(HelpSet hs){
+        for( Enumeration e = hs.getHelpSets(); e.hasMoreElements(); ) {
+	    HelpSet ehs = (HelpSet) e.nextElement();
+	    if (ehs == null) {
+		continue;
+	    }
+            // merge views
+            NavigatorView[] views = ehs.getNavigatorViews();
+            for(int i = 0; i < views.length; i++){
+		if (views[i] instanceof IndexView) {
+		    Merge mergeObject = 
+			Merge.DefaultMergeFactory.getMerge(view, views[i]);
+		    if (mergeObject != null) {
+			mergeObject.processMerge(topNode);
+		    }
+		}
+            }
+            addSubHelpSets( ehs );
+	}
+    }    
+
+    public int doStartTag() {
+	initialize();
+	if(treeEnum.hasMoreElements()) {
+	    DefaultMutableTreeNode node = 
+		(DefaultMutableTreeNode) treeEnum.nextElement();
+	    // never use the top node. It is just the container node
+ 	    if (node == topNode) {
+		try {
+		    node = (DefaultMutableTreeNode) treeEnum.nextElement();
+		} catch (NoSuchElementException e) {
+		    return SKIP_BODY;
+		}
+	    }
+	    setNodeAttributes(node);
+	    return EVAL_BODY_TAG;
+	}
+	else {
+	    return SKIP_BODY;
+	}
+    }
+
+    public int doAfterBody() throws JspException {
+	BodyContent body = getBodyContent();
+	try {
+	    body.writeOut(getPreviousOut());
+	} catch (IOException e) {
+	    throw new JspTagException("IndexItemTag: " + e.getMessage());
+	}
+	// clear up so the next time the body content is empty
+	body.clearBody();
+	if (treeEnum.hasMoreElements()) {
+	    DefaultMutableTreeNode node = 
+		(DefaultMutableTreeNode) treeEnum.nextElement();
+	    setNodeAttributes(node);
+	    return EVAL_BODY_TAG;
+	} else {
+	    return SKIP_BODY;
+	}
+    }
+
+    private void setNodeAttributes(DefaultMutableTreeNode node) {
+	    IndexItem item = (IndexItem) node.getUserObject();
+	    pageContext.setAttribute("name", item.getName());
+	    String helpID = "";
+	    if (item.getID() != null) {
+		helpID = item.getID().id;
+	    }
+	    pageContext.setAttribute("helpID", helpID);
+	    pageContext.setAttribute("parent", Integer.toHexString(node.getParent().hashCode()));
+	    String id = getID(node.getParent());
+	    pageContext.setAttribute("parentID", id);
+	    pageContext.setAttribute("node", Integer.toHexString(node.hashCode()));
+	    id = getID(node);
+	    pageContext.setAttribute("nodeID", id);
+	    String content = getContentURL(item);
+	    pageContext.setAttribute("contentURL", content);
+	    String expansionType = Integer.toString(item.getExpansionType());
+	    pageContext.setAttribute("expansionType", expansionType);
+    }
+
+    private String getID(TreeNode node) {
+	if (node == topNode) {
+	    return baseID;
+	}
+	TreeNode parent = node.getParent();
+	if (parent == null) {
+	    return "";
+	}
+	String id = getID(parent);
+        id = id.concat("." + Integer.toString(parent.getIndex(node)));
+	return id;
+    }
+
+    /**
+     * return the content URL in String form for a given IndexItem
+     * 
+     * returns an empty String if no content exists.
+     */
+    private String getContentURL(IndexItem item) {
+	URL url = null;
+	ID id = item.getID();
+	if (id != null) {
+	    HelpSet hs = id.hs;
+	    Map map = hs.getLocalMap();
+	    try {
+		url = map.getURLFromID(id);
+	    } catch (MalformedURLException e) {
+		// just ignore
+	    }
+	}
+	if (url == null) {
+	    return "";
+	}
+	return url.toExternalForm();
+    }
+
+}
+
diff --git a/jhMaster/JavaHelp/src/new/javax/help/tagext/NavigatorsTEI.java b/jhMaster/JavaHelp/src/new/javax/help/tagext/NavigatorsTEI.java
new file mode 100644
index 0000000000000000000000000000000000000000..bd610904c665fae13297719a23700fabf56b6b5a
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/tagext/NavigatorsTEI.java
@@ -0,0 +1,61 @@
+/*
+ * @(#)NavigatorsTEI.java	1.3 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help.tagext;
+
+import javax.servlet.jsp.tagext.*;
+
+/**
+ * The JSP tag extra info class for navigators
+ *
+ * @author Roger D. Brinkley
+ * @version	1.3	10/30/06
+ * @see javax.help.HelpSet.getNavigatorView()
+ * @see javax.help.NavigatorView
+ */
+
+public class NavigatorsTEI extends TagExtraInfo {
+  
+   public NavigatorsTEI() {
+      super();
+   }
+
+   public VariableInfo[] getVariableInfo(TagData data) {
+       return new VariableInfo[] {
+	   new VariableInfo("className", "java.lang.String", true, 
+			    VariableInfo.NESTED),
+	   new VariableInfo("name", "java.lang.String", true, 
+			    VariableInfo.NESTED),
+	   new VariableInfo("tip", "java.lang.String", true, 
+			    VariableInfo.NESTED),
+	   new VariableInfo("iconURL", "java.lang.String", true, 
+			    VariableInfo.NESTED),
+	   new VariableInfo("isCurrentNav", "java.lang.Boolean", true, 
+			    VariableInfo.NESTED),
+       };
+   }
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/tagext/NavigatorsTag.java b/jhMaster/JavaHelp/src/new/javax/help/tagext/NavigatorsTag.java
new file mode 100644
index 0000000000000000000000000000000000000000..b5f35ab7f7820c76c8ff97b5666b39da673251d7
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/tagext/NavigatorsTag.java
@@ -0,0 +1,158 @@
+/*
+ * @(#)NavigatorsTag.java	1.4 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help.tagext;
+
+import javax.servlet.jsp.*;
+import javax.servlet.jsp.tagext.*;
+import javax.servlet.ServletRequest;
+import java.util.*;
+import java.io.*;
+import java.net.URL;
+import java.net.MalformedURLException;
+import javax.help.HelpBroker;
+import javax.help.HelpSet;
+import javax.help.Map;
+import javax.help.Map.ID;
+import javax.help.NavigatorView;
+
+/**
+ * The JSP tag class for a Navigators
+ *
+ * @author Roger D. Brinkley
+ * @version	1.4	10/30/06
+ * @see javax.help.HelpSet.getNavigatorView()
+ * @see javax.help.NavigatorView
+ */
+
+public class NavigatorsTag extends BodyTagSupport {
+    private HelpBroker hb;
+    private HelpSet hs;
+    private String curNav = null;
+    private NavigatorView[] views;
+    private int i;
+
+    public void setHelpBroker(HelpBroker hb) {
+	this.hb = hb;
+	hs = hb.getHelpSet();
+    }
+
+    public void setCurrentNav(String nav) {
+	curNav = nav;
+    }
+
+    public void initialize() {
+	checkRequestParams();
+	initCurNav();
+	views = hs.getNavigatorViews();
+    }
+
+    public int doStartTag() {
+	initialize();
+	if(views.length > 0) {
+	    i = 0;
+	    setNavigatorAttributes(views[i++]);
+	    return EVAL_BODY_TAG;
+	} else {
+	    return SKIP_BODY;
+	}
+    }
+
+    private void checkRequestParams() {
+	ServletRequest request = pageContext.getRequest();
+
+	String nav = request.getParameter("nav");
+	if (nav != null) {
+	    curNav = nav;
+	}
+
+    }
+
+    private void initCurNav() {
+	if (curNav != null) {
+	    try {
+		hb.setCurrentView(curNav);
+	    } catch (IllegalArgumentException e) {
+		// Ignore
+	    }   
+	} else {
+	    curNav = hb.getCurrentView();
+	}
+    }
+
+
+    public int doAfterBody() throws JspException {
+	BodyContent body = getBodyContent();
+	try {
+	    body.writeOut(getPreviousOut());
+	} catch (IOException e) {
+	    throw new JspTagException("NavigatorsTag: " + e.getMessage());
+	}
+
+	// clear up so the next time the body content is empty
+	body.clearBody();
+	if (i < views.length) {
+	    setNavigatorAttributes(views[i++]);
+	    return EVAL_BODY_TAG;
+	} else {
+	    return SKIP_BODY;
+	}
+    }
+
+    private void setNavigatorAttributes(NavigatorView view) {
+	pageContext.setAttribute("className", view.getClass().getName());
+	pageContext.setAttribute("name", view.getName());
+	pageContext.setAttribute("tip", view.getLabel());
+	String icon = getIconURL(view);
+	pageContext.setAttribute("iconURL", icon);
+	pageContext.setAttribute("isCurrentNav", new Boolean(curNav.compareTo(view.getName()) == 0));
+    }
+
+    /**
+     * return the icon URL in String form for a given TOCItem
+     * 
+     * returns empty String if no content exists.
+     */
+    private String getIconURL(NavigatorView view) {
+	URL url = null;
+	ID id = view.getImageID();
+	if (id != null) {
+	    HelpSet hs = id.hs;
+	    Map map = hs.getLocalMap();
+	    try {
+		url = map.getURLFromID(id);
+	    } catch (MalformedURLException e) {
+		// just ignore
+	    }
+	}
+	if (url == null) {
+	    return "";
+	}
+	return url.toExternalForm();
+    }
+}
+
diff --git a/jhMaster/JavaHelp/src/new/javax/help/tagext/SearchTOCItemTEI.java b/jhMaster/JavaHelp/src/new/javax/help/tagext/SearchTOCItemTEI.java
new file mode 100644
index 0000000000000000000000000000000000000000..b0d19e8a9d25308ed9f5104f5be8a7c77db75a23
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/tagext/SearchTOCItemTEI.java
@@ -0,0 +1,62 @@
+/*
+ * @(#)SearchTOCItemTEI.java	1.2 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help.tagext;
+
+import javax.servlet.jsp.tagext.*;
+
+/**
+ * The JSP tag extra info class for an SearchTOCItem
+ *
+ * @author Roger D. Brinkley
+ * @version	1.2	10/30/06
+ * @see javax.help.SearchTOCItem
+ */
+
+public class SearchTOCItemTEI extends TagExtraInfo {
+  
+   public SearchTOCItemTEI() {
+      super();
+   }
+
+   public VariableInfo[] getVariableInfo(TagData data) {
+       return new VariableInfo[] {
+	   new VariableInfo("name", "java.lang.String", true, 
+			    VariableInfo.NESTED),
+	   new VariableInfo("helpID", "java.lang.String", true, 
+			    VariableInfo.NESTED),
+	   new VariableInfo("confidence", "java.lang.String", true, 
+			    VariableInfo.NESTED),
+	   new VariableInfo("hits", "java.lang.String", true, 
+			    VariableInfo.NESTED),
+	   new VariableInfo("contentURL", "java.lang.String", true, 
+			    VariableInfo.NESTED),
+	   new VariableInfo("hitBoundries", "java.lang.String", true, 
+			    VariableInfo.NESTED)
+       };
+   }
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/tagext/SearchTOCItemTag.java b/jhMaster/JavaHelp/src/new/javax/help/tagext/SearchTOCItemTag.java
new file mode 100644
index 0000000000000000000000000000000000000000..d837adeb4dae941ced643de025e12e6fa8cf6612
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/tagext/SearchTOCItemTag.java
@@ -0,0 +1,262 @@
+/*
+ * @(#)SearchTOCItemTag.java	1.3 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help.tagext;
+
+import javax.servlet.jsp.*;
+import javax.servlet.jsp.tagext.*;
+import java.util.*;
+import java.io.*;
+import java.net.URL;
+import java.net.MalformedURLException;
+import javax.help.HelpBroker;
+import javax.help.HelpSet;
+import javax.help.Map;
+import javax.help.Map.ID;
+import javax.help.NavigatorView;
+import javax.help.SearchTOCItem;
+import javax.help.SearchView;
+import javax.help.SearchHit;
+import javax.help.search.MergingSearchEngine;
+import javax.help.search.SearchQuery;
+import javax.help.search.SearchListener;
+import javax.help.search.SearchEvent;
+import javax.help.search.SearchItem;
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.TreeNode;
+
+/**
+ * The JSP tag extra info class for an SearchTOCItem
+ *
+ * @author Roger D. Brinkley
+ * @version	1.3	10/30/06
+ * @see javax.help.SearchTOCItem
+ */
+
+public class SearchTOCItemTag extends BodyTagSupport implements SearchListener{
+    private Enumeration treeEnum;
+    private Vector nodes;
+    private SearchView view;
+    private HelpBroker hb;
+    private String query;
+    private MergingSearchEngine helpsearch;
+    private SearchQuery searchquery;
+    private boolean searchFinished;
+
+    public void setSearchView(SearchView view) {
+	this.view = view;
+    }
+
+    public void setHelpBroker(HelpBroker hb) {
+	this.hb = hb;
+    }
+
+    public void setQuery(String query) {
+	this.query = query;
+    }
+
+
+    public synchronized int doStartTag() {
+	if (helpsearch == null) {
+	    helpsearch = new MergingSearchEngine(view);
+	    searchquery = helpsearch.createQuery();
+	    searchquery.addSearchListener(this);
+
+	    // Make sure all the subhelpsets have a search engine
+	    addSubHelpSets(view.getHelpSet());
+	}
+
+	if (searchquery.isActive()) {
+	    searchquery.stop();
+	}
+
+	searchquery.start(query, Locale.getDefault());
+
+	if (!searchFinished) {
+	    try {
+		wait();
+	    } catch (InterruptedException e) {
+		// ignore
+	    }
+	}
+
+
+	if(treeEnum.hasMoreElements()) {
+	    SearchTOCItem item = (SearchTOCItem) treeEnum.nextElement();
+	    setNodeAttributes(item);
+	    return EVAL_BODY_TAG;
+	} else {
+	    return SKIP_BODY;
+	}
+    }
+
+    /** Adds subhelpsets
+     *
+     * @param hs The HelpSet which subhelpsets will be added
+     */
+    private void addSubHelpSets(HelpSet hs){
+        for( Enumeration e = hs.getHelpSets(); e.hasMoreElements(); ) {
+	    HelpSet ehs = (HelpSet) e.nextElement();
+	    if (ehs == null) {
+		continue;
+	    }
+            // merge views
+            NavigatorView[] views = ehs.getNavigatorViews();
+            for(int i = 0; i < views.length; i++){
+		if (views[i] instanceof SearchView) {
+		    helpsearch.merge(views[i]);
+		}
+            }
+            addSubHelpSets( ehs );
+	}
+    }    
+
+    public int doAfterBody() throws JspException {
+	BodyContent body = getBodyContent();
+	try {
+	    body.writeOut(getPreviousOut());
+	} catch (IOException e) {
+	    throw new JspTagException("SearchTOCItemTag: " + e.getMessage());
+	}
+
+	// clear up so the next time the body content is empty
+	body.clearBody();
+	if(treeEnum.hasMoreElements()) {
+	    SearchTOCItem item = (SearchTOCItem) treeEnum.nextElement();
+	    setNodeAttributes(item);
+	    return EVAL_BODY_TAG;
+	} else {
+	    return SKIP_BODY;
+	}
+    }
+
+    private void setNodeAttributes(SearchTOCItem item) {
+	pageContext.setAttribute("name", item.getName());
+	pageContext.setAttribute("helpID", getMapID(item));
+	pageContext.setAttribute("confidence", Double.toString(item.getConfidence()));
+	pageContext.setAttribute("hits", Integer.toString(item.hitCount()));
+	pageContext.setAttribute("contentURL", item.getURL().toExternalForm());
+	pageContext.setAttribute("hitBoundries", getSearchHits(item));
+    }
+
+    /**
+     * return an Map.ID if one exists for the content URL for a given SearchTOCItem
+     * 
+     * returns an empty String if no content exists.
+     */
+    private String getMapID(SearchTOCItem item) {
+	URL url = item.getURL();
+	HelpSet hs = hb.getHelpSet();
+	Map map = hs.getCombinedMap();
+	ID id = map.getIDFromURL(url);
+	if (id == null) {
+	    return "";
+	}
+	return id.id;
+    }
+
+    /**
+     * Get a string representing the array of SearchHit's begin and end locations
+     * for each hit
+     * 
+     * @return String a sring representation of the values
+     */
+    private String getSearchHits(SearchTOCItem item) {
+	String retval = "{ ";
+	for (Enumeration enum1 = item.getSearchHits();
+	     enum1.hasMoreElements();) {
+	    SearchHit info = (SearchHit) enum1.nextElement();
+	    retval = retval + "{" + info.getBegin() + "," + info.getEnd() + 
+		"}";
+	    if (enum1.hasMoreElements()) {
+		retval = retval + ", ";
+	    }
+	}
+	retval = retval + " }";
+	return retval;
+    }
+	
+
+    public synchronized void itemsFound(SearchEvent e) {
+	SearchTOCItem tocitem;
+	Enumeration itemEnum = e.getSearchItems();
+	// Iterate through each search item in the searchEvent
+	while (itemEnum.hasMoreElements()) {
+	    SearchItem item = (SearchItem) itemEnum.nextElement();
+	    URL url;
+	    try {
+		url = new URL(item.getBase(), item.getFilename());
+	    } catch (MalformedURLException me) {
+		debug ("Failed to create URL from " + item.getBase() + "|" +
+		       item.getFilename());
+		continue;
+	    }
+	    boolean foundNode = false;
+
+	    // see if this search item matches that of one we currently have
+	    // if so just do an update
+	    Enumeration nodesEnum = nodes.elements();
+	    while (nodesEnum.hasMoreElements()) {
+		tocitem = (SearchTOCItem) nodesEnum.nextElement();
+		URL testURL = tocitem.getURL();
+		if (testURL != null && url != null && url.sameFile(testURL)) {
+		    tocitem.addSearchHit(new SearchHit(item.getConfidence(),
+						       item.getBegin(),
+						       item.getEnd()));
+		    foundNode = true;
+		    break;
+		}
+	    }
+
+	    // No match. 
+	    // OK then add a new one.
+	    if (!foundNode) {
+		tocitem = new SearchTOCItem(item);
+		nodes.addElement(tocitem);
+	    }
+	}
+    }
+
+    public synchronized void searchStarted(SearchEvent e) {
+	nodes = new Vector();
+	searchFinished = false;
+    }
+
+    public synchronized void searchFinished(SearchEvent e) {
+	searchFinished = true;
+	treeEnum = nodes.elements();
+	notifyAll();
+    }
+
+    private static final boolean debug = false;
+    private static void debug(String msg) {
+	if (debug) {
+	    System.err.println("SearchTOCItemTag: "+msg);
+	}
+    }
+}
+
diff --git a/jhMaster/JavaHelp/src/new/javax/help/tagext/TOCItemTEI.java b/jhMaster/JavaHelp/src/new/javax/help/tagext/TOCItemTEI.java
new file mode 100644
index 0000000000000000000000000000000000000000..adeebaf4d1e5eab9458ec839ca4f6945bfa9b0d4
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/tagext/TOCItemTEI.java
@@ -0,0 +1,70 @@
+/*
+ * @(#)TOCItemTEI.java	1.3 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help.tagext;
+
+import javax.servlet.jsp.tagext.*;
+
+/**
+ * The JSP tag extra info class for an TOCItem
+ *
+ * @author Roger D. Brinkley
+ * @version	1.3	10/30/06
+ * @see javax.help.TOCItem
+ */
+
+public class TOCItemTEI extends TagExtraInfo {
+  
+   public TOCItemTEI() {
+      super();
+   }
+
+   public VariableInfo[] getVariableInfo(TagData data) {
+       return new VariableInfo[] {
+	   new VariableInfo("name", "java.lang.String", true, 
+			    VariableInfo.NESTED),
+	   new VariableInfo("helpID", "java.lang.String", true, 
+			    VariableInfo.NESTED),
+	   new VariableInfo("parent", "java.lang.String", true, 
+			    VariableInfo.NESTED),
+	   new VariableInfo("parentID", "java.lang.String", true, 
+			    VariableInfo.NESTED),
+	   new VariableInfo("node", "java.lang.String", true, 
+			    VariableInfo.NESTED),
+	   new VariableInfo("nodeID", "java.lang.String", true, 
+			    VariableInfo.NESTED),
+	   new VariableInfo("iconURL", "java.lang.String", true, 
+			    VariableInfo.NESTED),
+	   new VariableInfo("iconOpenURL", "java.lang.String", true, 
+			    VariableInfo.NESTED),
+	   new VariableInfo("contentURL", "java.lang.String", true, 
+			    VariableInfo.NESTED),
+	   new VariableInfo("expansionType", "java.lang.String", true, 
+			    VariableInfo.NESTED)
+       };
+   }
+}
diff --git a/jhMaster/JavaHelp/src/new/javax/help/tagext/TOCItemTag.java b/jhMaster/JavaHelp/src/new/javax/help/tagext/TOCItemTag.java
new file mode 100644
index 0000000000000000000000000000000000000000..7350bd932a50d755ea18c51b55e086621fdd71d6
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/tagext/TOCItemTag.java
@@ -0,0 +1,258 @@
+/*
+ * @(#)TOCItemTag.java	1.5 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help.tagext;
+
+import javax.servlet.jsp.*;
+import javax.servlet.jsp.tagext.*;
+import java.util.*;
+import java.io.*;
+import java.net.URL;
+import java.net.MalformedURLException;
+import javax.help.HelpBroker;
+import javax.help.HelpSet;
+import javax.help.Map;
+import javax.help.Map.ID;
+import javax.help.Merge;
+import javax.help.MergeHelpUtilities;
+import javax.help.NavigatorView;
+import javax.help.TOCItem;
+import javax.help.TOCView;
+import javax.help.SortMerge;
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.TreeNode;
+
+/**
+ * The JSP tag extra info class for an TocItem
+ *
+ * @author Roger D. Brinkley
+ * @version	1.5	10/30/06
+ * @see javax.help.TOCItem
+ */
+
+public class TOCItemTag extends BodyTagSupport {
+    private Enumeration treeEnum;
+    private DefaultMutableTreeNode topNode;
+    private String baseID="root";
+    private HelpBroker hb;
+    private TOCView view=null;
+
+    public void setTocView(TOCView view) {
+	this.view = view;
+    }
+
+    public void setBaseID(String baseID) {
+	this.baseID = baseID;
+    }
+
+    public void setHelpBroker(HelpBroker hb) {
+	this.hb = hb;
+    }
+
+    private void initialize() {
+	if (view == null) {
+	    return;
+	}
+	topNode = view.getDataAsTree();
+
+	String mergeType = view.getMergeType();
+	HelpSet hs = view.getHelpSet();
+        Locale locale = hs.getLocale();
+
+
+	// Make sure the children are all handled correctly
+	MergeHelpUtilities.mergeNodeChildren(mergeType, topNode);
+        
+	// add all the subhelpsets
+        addSubHelpSets(hs);
+
+	treeEnum = topNode.preorderEnumeration();
+    }
+
+    /** Adds subhelpsets
+     *
+     * @param hs The HelpSet which subhelpsets will be added
+     */
+    private void addSubHelpSets(HelpSet hs){
+        for( Enumeration e = hs.getHelpSets(); e.hasMoreElements(); ) {
+	    HelpSet ehs = (HelpSet) e.nextElement();
+	    if (ehs == null) {
+		continue;
+	    }
+            // merge views
+            NavigatorView[] views = ehs.getNavigatorViews();
+            for(int i = 0; i < views.length; i++){
+		if (views[i] instanceof TOCView) {
+		    Merge mergeObject = 
+			Merge.DefaultMergeFactory.getMerge(view, views[i]);
+		    if (mergeObject != null) {
+			mergeObject.processMerge(topNode);
+		    }
+		}
+            }
+            addSubHelpSets( ehs );
+	}
+    }    
+
+    public int doStartTag() {
+	initialize();
+	if(treeEnum.hasMoreElements()) {
+	    DefaultMutableTreeNode node = 
+		(DefaultMutableTreeNode) treeEnum.nextElement();
+	    // never use the top node. It is just the container node
+ 	    if (node == topNode) {
+		try {
+		    node = (DefaultMutableTreeNode) treeEnum.nextElement();
+		} catch (NoSuchElementException e) {
+		    return SKIP_BODY;
+		}
+	    }
+	    setNodeAttributes(node);
+	    return EVAL_BODY_TAG;
+	}
+	else {
+	    return SKIP_BODY;
+	}
+    }
+
+    public int doAfterBody() throws JspException {
+	BodyContent body = getBodyContent();
+	try {
+	    body.writeOut(getPreviousOut());
+	} catch (IOException e) {
+	    throw new JspTagException("TOCItemTag: " + e.getMessage());
+	}
+
+	// clear up so the next time the body content is empty
+	body.clearBody();
+	if (treeEnum.hasMoreElements()) {
+	    DefaultMutableTreeNode node = 
+		(DefaultMutableTreeNode) treeEnum.nextElement();
+	    setNodeAttributes(node);
+	    return EVAL_BODY_TAG;
+	} else {
+	    return SKIP_BODY;
+	}
+    }
+
+    private void setNodeAttributes(DefaultMutableTreeNode node) {
+	TOCItem item = (TOCItem) node.getUserObject();
+	pageContext.setAttribute("name", item.getName());
+	String helpID = "";
+	if (item.getID() != null) {
+	    helpID = item.getID().id;
+	}
+	pageContext.setAttribute("helpID", helpID);
+	pageContext.setAttribute("parent", Integer.toHexString(node.getParent().hashCode()));
+	String id = getID(node.getParent());
+	pageContext.setAttribute("parentID", id);
+	pageContext.setAttribute("node", Integer.toHexString(node.hashCode()));
+	id = getID(node);
+	pageContext.setAttribute("nodeID", id);
+	String content = getContentURL(item);
+	pageContext.setAttribute("contentURL", content);
+	String icon = getIconURL(node, item, true);
+	pageContext.setAttribute("iconURL", icon);
+	String iconOpen = getIconURL(node, item, false);
+	pageContext.setAttribute("iconOpenURL", iconOpen);
+	String expansionType = Integer.toString(item.getExpansionType());
+	pageContext.setAttribute("expansionType", expansionType);
+    }
+
+    private String getID(TreeNode node) {
+	if (node == topNode) {
+	    return baseID;
+	}
+	TreeNode parent = node.getParent();
+	if (parent == null) {
+	    return "";
+	}
+	String id = getID(parent);
+        id = id.concat("_" + Integer.toString(parent.getIndex(node)));
+	return id;
+    }
+
+    /**
+     * return the content URL in String form for a given TOCItem
+     * 
+     * returns an empty String if no content exists.
+     */
+    private String getContentURL(TOCItem item) {
+	URL url = null;
+	ID id = item.getID();
+	if (id != null) {
+	    HelpSet hs = id.hs;
+	    Map map = hs.getLocalMap();
+	    try {
+		url = map.getURLFromID(id);
+	    } catch (MalformedURLException e) {
+		// just ignore
+	    }
+	}
+	if (url == null) {
+	    return "";
+	}
+	return url.toExternalForm();
+    }
+
+    /**
+     * return the icon URL in String form for a given TOCItem
+     * 
+     * returns empty String if no content exists.
+     */
+    private String getIconURL(DefaultMutableTreeNode node,
+			      TOCItem item, 
+			      boolean closedIcon) {
+	URL url = null;
+	ID id = item.getImageID();
+	if (id == null) {
+	    if (node.isLeaf()) {
+		id = view.getTopicImageID();
+	    } else {
+		if (closedIcon) {
+		    id = view.getCategoryClosedImageID();
+		} else {
+		    id = view.getCategoryOpenImageID();
+		}
+	    }
+	}
+	if (id != null) {
+	    HelpSet hs = id.hs;
+	    Map map = hs.getLocalMap();
+	    try {
+		url = map.getURLFromID(id);
+	    } catch (MalformedURLException e) {
+		// just ignore
+	    }
+	}
+	if (url == null) {
+	    return "";
+	}
+	return url.toExternalForm();
+    }
+}
+
diff --git a/jhMaster/JavaHelp/src/new/javax/help/tagext/ValidateTag.java b/jhMaster/JavaHelp/src/new/javax/help/tagext/ValidateTag.java
new file mode 100644
index 0000000000000000000000000000000000000000..6debf6c61f7887560287100f1d739983337edaa6
--- /dev/null
+++ b/jhMaster/JavaHelp/src/new/javax/help/tagext/ValidateTag.java
@@ -0,0 +1,173 @@
+/*
+ * @(#)ValidateTag.java	1.3 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.help.tagext;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletException;
+import javax.servlet.jsp.tagext.TagSupport;
+import javax.servlet.jsp.tagext.Tag;
+import javax.help.HelpBroker;
+import javax.help.HelpSet;
+import javax.help.HelpSetException;
+import javax.help.InvalidHelpSetContextException;
+
+/**
+ * Validates a HelpSet file and an Map.ID thourgh either a Request Parameter
+ * or passed as a JSP argument and sets the state in a HelpBroker. Additionally
+ * allows a HelpSet to be merged with the current HelpSet in the HelpBroker.
+ *
+ * @author Roger D. BRinkley
+ * @version	1.3	10/30/06
+ * @see javax.help.HelpSet
+ * @see javax.help.Map.ID
+ * @see javax.help.HelpBroker
+ */
+
+public class ValidateTag extends TagSupport {
+    private HelpBroker helpBroker;
+    private String invalidURLPath = "invalidhelp.html";
+    private String hsName = null;
+    private String id = null;
+    private boolean merge = false;
+
+    public void setHelpBroker(HelpBroker helpBroker) {
+	this.helpBroker = helpBroker;
+    }
+
+    public void setInvalidURL(String relativeURLPath) {
+	this.invalidURLPath = relativeURLPath;
+    }
+
+    public void setHelpSetName(String hsName) {
+	this.hsName = hsName;
+    }
+
+    public void setCurrentID(String id) {
+	this.id = id;
+    }
+
+    public void setMerge(boolean merge) {
+	this.merge = merge;
+    }
+
+    public int doStartTag() {
+	checkRequestParams();
+	validateHelpSet();
+	validateID();
+	return SKIP_BODY;
+    }
+
+    private void checkRequestParams() {
+	ServletRequest request = pageContext.getRequest();
+
+	if (hsName == null) {
+	    hsName = request.getParameter("helpset");
+	}
+
+	if (id == null) {
+	    id = request.getParameter("id");
+	}
+    }
+
+    private void validateHelpSet() {
+	HelpSet tesths = helpBroker.getHelpSet();
+
+	// If there is already a HelpSet and there isn't a hsName
+	// return. Nothing to do
+	if (tesths != null && hsName == null) {
+	    return;
+	}
+
+	// If there isn't a HelpSet and there isn't a hsName
+	// then forward to the invalid page
+	if (tesths == null && hsName == null) {
+	    try {
+		pageContext.forward(invalidURLPath);
+	    } catch (Exception e) {
+		// ignore it
+		return;
+	    }
+	} 
+
+
+	// If we don't have a helpset and there is a hsName
+	// the create one and set the HelpBroker to this page
+	if (tesths == null && hsName != null) {
+	    helpBroker.setHelpSet(createHelpSet());
+	    return;
+	} 
+
+	// If we have a helpset and there is a hsname
+	// and merging is turned on, merge the helpset
+	if (tesths != null && hsName != null && merge) {
+	    tesths.add(createHelpSet());
+	}
+    }
+
+    private HelpSet createHelpSet() {
+	HelpSet hs = null;
+	ServletRequest request = pageContext.getRequest();
+	if (!hsName.startsWith("/")) {
+	    hsName = "/" + hsName;
+	}
+	URL url = null;
+	try {
+	    if (hsName.startsWith("http")) {
+		url = new URL (hsName);
+	    } else {
+		url = new URL(request.getScheme(),
+			      request.getServerName(),
+			      request.getServerPort(),
+			      hsName);
+	    }
+	    hs = new HelpSet(null, url);
+	} catch (MalformedURLException e) {
+	    // ignore
+	} catch (HelpSetException hse) {
+	    // this is a serious error
+	    throw new RuntimeException(hse.getMessage());
+	}
+	return hs;
+    }
+
+    private void validateID() {
+	if (id != null) {
+	    helpBroker.setCurrentID(id);
+	} else if (helpBroker.getCurrentID() == null && 
+		   helpBroker.getCurrentURL() == null) {
+	    try {
+		helpBroker.setCurrentID(helpBroker.getHelpSet().getHomeID());
+	    } catch (InvalidHelpSetContextException e) {
+		// ignore
+	    }
+	}
+    }
+}
+
diff --git a/jhMaster/JavaHelp/test/editorKit/HtmlTest.java b/jhMaster/JavaHelp/test/editorKit/HtmlTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..db1104c1452af38203bfe93a2affcdf1d9982bcf
--- /dev/null
+++ b/jhMaster/JavaHelp/test/editorKit/HtmlTest.java
@@ -0,0 +1,349 @@
+/*
+ * @(#)HtmlTest.java	1.2 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+import javax.swing.*;
+import javax.swing.event.*;
+import javax.swing.text.*;
+import javax.swing.text.html.*;
+import javax.swing.tree.*;
+import javax.swing.undo.*;
+import java.awt.*;
+import java.util.*;
+import java.net.URL;
+import java.net.MalformedURLException;
+import java.io.IOException;
+
+/**
+ * Simple wrapper around JEditorPane to browse html.
+ * Useful to browse the javadoc for swing... 
+ * java HtmlTest file:/path-to-swing-docs/packages.html
+ */
+public class HtmlTest {
+
+    public static void main(String[] args) {
+	Properties props =  System.getProperties();
+	props.put("http.proxyHost", "webcache1.eng");
+	props.put("http.proxyPort", "8080");
+
+	if (args.length != 1) {
+	    System.err.println("need URL argument");
+	    System.exit(1);
+	}
+	try {
+	    URL u = new URL(args[0]);
+	    JEditorPane html = new JEditorPane(u);
+	    html.setEditable(false);
+	    html.addHyperlinkListener(new Hyperactive());
+	    html.setBackground(Color.white);
+	    JScrollPane scroller = new JScrollPane();
+	    JViewport vp = scroller.getViewport();
+	    vp.add(html);
+	    vp.setBackingStoreEnabled(true);
+
+	    JFrame f = new JFrame("testing");
+	    f.getContentPane().setLayout(new BorderLayout());
+	    f.getContentPane().add("Center", scroller);
+	    f.pack();
+	    f.setSize(600, 600);
+	    f.setVisible(true);
+
+	    JFrame elems = new JFrame("elements");
+	    Container fContentPane = elems.getContentPane();
+	    fContentPane.setLayout(new BorderLayout());
+	    fContentPane.add(new ElementTreePanel(html));
+	    elems.pack();
+	    elems.show();
+	} catch (MalformedURLException e) {
+	    System.err.println("Bad url");
+	    System.exit(1);
+	} catch (IOException ioe) {
+	    System.err.println("IOException: " + ioe.getMessage());
+	    System.exit(1);
+	}
+    }
+
+    static class Hyperactive implements HyperlinkListener {
+
+	/**
+	 * Notification of a change relative to a 
+	 * hyperlink.
+	 */
+        public void hyperlinkUpdate(HyperlinkEvent e) {
+	    System.err.println("link event: " + e);
+	    if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
+		JEditorPane html = (JEditorPane) e.getSource();
+		if (e instanceof HTMLFrameHyperlinkEvent) {
+		    HTMLFrameHyperlinkEvent  evt = (HTMLFrameHyperlinkEvent)e;
+		    HTMLDocument doc = (HTMLDocument)html.getDocument();
+		    doc.processHTMLFrameHyperlinkEvent(evt);
+		} else {
+		    try {
+			html.setPage(e.getURL());
+		    } catch (Throwable t) {
+			t.printStackTrace();
+		    }
+		}
+	    }
+	}
+    }
+
+/**
+ * Displays a tree showing all the elements in a text Document. Selecting
+ * a node will result in reseting the selection of the JTextComponent.
+ *
+ * @author Scott Violet
+ * @version 1.1 04/28/98
+ */
+static class ElementTreePanel extends JPanel implements DocumentListener, TreeSelectionListener {
+    /** Tree showing the documents element structure. */
+    protected JTree             tree;
+    /** Text component showing elemenst for. */
+    protected JTextComponent    editor;
+    /** Model for the tree. */
+    protected DefaultTreeModel  treeModel;
+
+    public ElementTreePanel(JTextComponent editor) {
+	this.editor = editor;
+
+	Document document = editor.getDocument();
+
+	// Create the tree.
+	treeModel = new DefaultTreeModel((TreeNode)document.
+					 getDefaultRootElement());
+	tree = new JTree(treeModel) {
+	    public String convertValueToText(Object value, boolean selected,
+					     boolean expanded, boolean leaf,
+					     int row, boolean hasFocus) {
+		Element        e = (Element)value;
+		AttributeSet   as = e.getAttributes().copyAttributes();
+		String         asString;
+
+		if(as != null) {
+		    StringBuffer       retBuffer = new StringBuffer("[");
+		    Enumeration        names = as.getAttributeNames();
+	    
+		    while(names.hasMoreElements()) {
+			Object        nextName = names.nextElement();
+
+			if(nextName != StyleConstants.ResolveAttribute) {
+			    retBuffer.append(" ");
+			    retBuffer.append(nextName);
+			    retBuffer.append("=");
+			    retBuffer.append(as.getAttribute(nextName));
+			}
+		    }
+		    retBuffer.append(" ]");
+		    asString = retBuffer.toString();
+		}
+		else
+		    asString = "[ ]";
+
+		if(e.isLeaf())
+		    return "LEAF: " + e.getName() + " Attributes: " + asString;
+		return "Branch: " + e.getName() + " Attributes: " +
+ 		        asString;
+	    }
+	};
+	tree.addTreeSelectionListener(this);
+	// become a listener on the document to update the tree.
+	document.addDocumentListener(this);
+
+	// configure the panel and frame containing it.
+	setLayout(new BorderLayout());
+	add(new JScrollPane(tree), BorderLayout.CENTER);
+
+	// Add a label above tree to describe what is being shown
+	JLabel     label = new JLabel("Elements that make up the current document", SwingConstants.CENTER);
+
+	label.setFont(new Font("Dialog", Font.BOLD, 14));
+	add(label, BorderLayout.NORTH);
+
+	setPreferredSize(new Dimension(400, 400));
+    }
+
+
+    // DocumentListener
+
+    /**
+     * Gives notification that there was an insert into the document.  The 
+     * given range bounds the freshly inserted region.
+     *
+     * @param e the document event
+     */
+    public void insertUpdate(DocumentEvent e) {
+	updateTree(e);
+    }
+
+    /**
+     * Gives notification that a portion of the document has been 
+     * removed.  The range is given in terms of what the view last
+     * saw (that is, before updating sticky positions).
+     *
+     * @param e the document event
+     */
+    public void removeUpdate(DocumentEvent e) {
+	updateTree(e);
+    }
+
+    /**
+     * Gives notification that an attribute or set of attributes changed.
+     *
+     * @param e the document event
+     */
+    public void changedUpdate(DocumentEvent e) {
+	updateTree(e);
+    }
+
+    // TreeSelectionListener
+
+    /** 
+      * Called whenever the value of the selection changes.
+      * @param e the event that characterizes the change.
+      */
+    public void valueChanged(TreeSelectionEvent e) {
+	JTree       tree = getTree();
+
+	if(tree.getSelectionCount() == 1) {
+	    TreePath      selPath = tree.getSelectionPath();
+	    Element       selElement = (Element)selPath.getLastPathComponent();
+
+	    getEditor().select(selElement.getStartOffset(),
+			       selElement.getEndOffset());
+	}
+    }
+
+    // Local methods
+
+    /**
+     * @return tree showing elements.
+     */
+    protected JTree getTree() {
+	return tree;
+    }
+
+    /**
+     * @return JTextComponent showing elements for.
+     */
+    protected JTextComponent getEditor() {
+	return editor;
+    }
+
+    /**
+     * @return root element of editor.
+     */
+    protected Element getRootElement() {
+	return getEditor().getDocument().getDefaultRootElement();
+    }
+
+    /**
+     * @return TreeModel implementation used to represent the elements.
+     */
+    public DefaultTreeModel getTreeModel() {
+	return treeModel;
+    }
+
+    /**
+     * Updates the tree based on the event type. This will invoke either
+     * updateTree with the root element, or handleChange.
+     */
+    protected void updateTree(DocumentEvent event) {
+	updateTree(event, getRootElement());
+    }
+
+    /**
+     * Creates TreeModelEvents based on the DocumentEvent and messages
+     * the treemodel. This recursively invokes this method with children
+     * elements.
+     * @param event indicates what elements in the tree hierarchy have
+     * changed.
+     * @param element Current element to check for changes against.
+     */
+    protected void updateTree(DocumentEvent event, Element element) {
+        DocumentEvent.ElementChange ec = event.getChange(element);
+
+        if (ec != null) {
+	    Element[]       removed = ec.getChildrenRemoved();
+	    Element[]       added = ec.getChildrenAdded();
+	    int             startIndex = ec.getIndex();
+
+	    // Check for removed.
+	    if(removed != null && removed.length > 0) {
+		int[]            indices = new int[removed.length];
+
+		for(int counter = 0; counter < removed.length; counter++) {
+		    indices[counter] = startIndex + counter;
+		}
+		getTreeModel().nodesWereRemoved((TreeNode)element, indices,
+						removed);
+	    }
+	    // check for added
+	    if(added != null && added.length > 0) {
+		int[]            indices = new int[added.length];
+
+		for(int counter = 0; counter < added.length; counter++) {
+		    indices[counter] = startIndex + counter;
+		}
+		getTreeModel().nodesWereInserted((TreeNode)element, indices);
+	    }
+        }
+	else if(!element.isLeaf()) {
+	    // If the event is a CHANGE, then need to forward to all
+	    // elements in effected range.
+	    // Otherwise, only forward to element at the offset of the
+	    // event.
+	    if(event.getType() == DocumentEvent.EventType.CHANGE) {
+		int        startIndex = element.getElementIndex
+		                       (event.getOffset());
+		int        endIndex = Math.min(element.getElementCount() - 1,
+					       element.getElementIndex
+				     (event.getOffset() + event.getLength()));
+
+		if(startIndex != -1 && endIndex != -1) {
+		    for(int counter = startIndex; counter <= endIndex;
+			counter++) {
+			updateTree(event, element.getElement(counter));
+		    }
+		}
+	    }
+	    else {
+		// Element hasn't changed, find the child in the effected
+		// region and forward.
+		int       childIndex = element.getElementIndex
+		                       (event.getOffset());
+
+		if(childIndex >= 0 && childIndex < element.getElementCount())
+		    updateTree(event, element.getElement(childIndex));
+	    }
+	}
+	else {
+	    // Element is a leaf, assume it changed
+	    getTreeModel().nodeChanged((TreeNode)element);
+	}
+    }
+}
+
+}
diff --git a/jhMaster/JavaHelp/test/i18n/GNUmakefile b/jhMaster/JavaHelp/test/i18n/GNUmakefile
new file mode 100644
index 0000000000000000000000000000000000000000..1fce85a9bbfd70159f760ff48836a9c78436aa83
--- /dev/null
+++ b/jhMaster/JavaHelp/test/i18n/GNUmakefile
@@ -0,0 +1,45 @@
+#
+# @(#)GNUmakefile	1.3 06/10/30
+# 
+# Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+# 
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.  Sun designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Sun in the LICENSE file that accompanied this code.
+# 
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+# 
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+# 
+# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+# CA 95054 USA or visit www.sun.com if you need additional information or
+# have any questions.
+#
+
+CLASSPATH = ../../build/jdk12/lib/jh.jar
+
+SRC= GetLocalizedResource.java
+
+TESTS=$(SRC:.java=.class)
+RUNS=$(SRC:.java=.run)
+
+all: $(TESTS)
+
+run: $(TESTS) $(RUNS)
+
+%.class: %.java
+	export CLASSPATH; CLASSPATH=$(CLASSPATH) ;\
+	javac $<
+
+%.run: %.java
+	export CLASSPATH; CLASSPATH=.:$(CLASSPATH) ;\
+	java $*
diff --git a/jhMaster/JavaHelp/test/i18n/GetLocalizedResource.java b/jhMaster/JavaHelp/test/i18n/GetLocalizedResource.java
new file mode 100644
index 0000000000000000000000000000000000000000..1fc30c9aa7a6e001ff91d0d3cc7e8dc4b07e553a
--- /dev/null
+++ b/jhMaster/JavaHelp/test/i18n/GetLocalizedResource.java
@@ -0,0 +1,71 @@
+/*
+ * @(#)GetLocalizedResource.java	1.3 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+import javax.javahelp.*;
+import java.net.URL;
+import java.util.Locale;
+
+public class GetLocalizedResource {
+    private static ClassLoader loader = GetLocalizedResource.class.getClassLoader();
+
+    private static int count = 0;
+
+    private static void error(String msg) {
+	count += 1;
+	System.err.println(msg);
+    }
+
+    private static void exists(String front, String back, Locale locale) {
+	URL url;
+	url = HelpUtilities.getLocalizedResource(loader,
+						 front, back,
+						 locale);
+	if (url == null) {
+	    error("Could not find resource.\n"+
+		  "  front: "+front+"\n"+
+		  "  back: "+back+"\n"+
+		  "  locale: "+locale);
+	} else {
+	    System.err.println("Found "+url+" for\n"+
+			       "  front: "+front+"\n"+
+			       "  back: "+back+"\n"+
+			       "  locale: "+locale);
+	}
+    }
+
+    public static void main(String args[]) {
+	exists("foo", ".hs", Locale.getDefault());
+	exists("foo", ".hs", Locale.getDefault());
+	exists("foo", ".hs", Locale.JAPANESE);
+	exists("foo", ".hs", Locale.CANADA_FRENCH);
+	exists("foo", ".hs", Locale.TAIWAN);
+	exists("foo", ".hs", Locale.JAPANESE);
+	if (count != 0) {
+	    throw new Error("Errors found");
+	}
+    }
+}
diff --git a/jhMaster/JavaHelp/test/misc/GNUmakefile b/jhMaster/JavaHelp/test/misc/GNUmakefile
new file mode 100644
index 0000000000000000000000000000000000000000..653ddecb783f0407fef5464602e13ae06ff30f15
--- /dev/null
+++ b/jhMaster/JavaHelp/test/misc/GNUmakefile
@@ -0,0 +1,46 @@
+#
+# @(#)GNUmakefile	1.2 06/10/30
+# 
+# Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+# 
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.  Sun designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Sun in the LICENSE file that accompanied this code.
+# 
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+# 
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+# 
+# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+# CA 95054 USA or visit www.sun.com if you need additional information or
+# have any questions.
+#
+
+CLASSPATH = ../../build/lib/jh.jar
+
+SRC= JHOptionTest.java
+
+TESTS=$(SRC:.java=.class)
+RUNS=$(SRC:.java=.run)
+
+all: $(TESTS)
+
+run: $(TESTS) $(RUNS)
+
+%.class: %.java
+	export CLASSPATH; CLASSPATH=$(CLASSPATH) ;\
+	javac $<
+
+%.run: %.java
+	export CLASSPATH; CLASSPATH=.:$(CLASSPATH) ;\
+	java $*
+
diff --git a/jhMaster/JavaHelp/test/misc/JHOptionTest.java b/jhMaster/JavaHelp/test/misc/JHOptionTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..640d72d80397a8edbf1ad4e283bb768d41903fc0
--- /dev/null
+++ b/jhMaster/JavaHelp/test/misc/JHOptionTest.java
@@ -0,0 +1,306 @@
+/*
+ * @(#)JHOptionTest.java	1.4 06/10/30
+ * 
+ * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * JHOptionTest.java
+ */
+
+import javax.javahelp.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import javax.swing.text.*;
+import javax.swing.border.*;
+import javax.accessibility.*;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.beans.*;
+import java.util.*;
+import java.io.*;
+import java.applet.*;
+import java.net.*;
+
+/**
+ * A demo that tests the JOptionPane optiontypes
+ *
+ */
+public class JHOptionTest extends JPanel
+{
+    // This
+    JHOptionTest opttest;
+
+    // The Frame
+    public static JFrame frame;
+
+    // The width and height of the frame
+    public static int WIDTH = 790;
+    public static int HEIGHT = 550;
+    public static int INITIAL_WIDTH = 400;
+    public static int INITIAL_HEIGHT = 200;
+
+    public Font defaultFont = new Font("Dialog", Font.PLAIN, 12);
+
+    public JHOptionTest() {
+	super(true); // double buffer
+
+	opttest = this;
+	setName("Main JHOptionTest Panel");
+	setFont(defaultFont);
+	setLayout(new BorderLayout());
+
+	// Add a MenuBar
+	add(createMenuBar(), BorderLayout.NORTH);
+
+    }
+
+    /*******************************************/
+    /************ create components ************/
+    /*******************************************/
+
+    /**
+     * MenuBar
+     */
+    Dialog aboutBox;
+    JCheckBoxMenuItem cb;
+    JRadioButtonMenuItem rb;
+
+    JMenuBar createMenuBar() {
+	// MenuBar
+	JMenuBar menuBar = new JMenuBar();
+	menuBar.getAccessibleContext().setAccessibleName("Swing menus");
+
+	JMenuItem mi;
+
+	// File Menu
+	JMenu file = (JMenu) menuBar.add(new JMenu("File"));
+        file.setMnemonic('F');
+        mi = (JMenuItem) file.add(new JMenuItem("Exit"));
+        mi.setMnemonic('x');
+	mi.getAccessibleContext().setAccessibleDescription("Exit the JHOptionTest application");
+	mi.addActionListener(new ActionListener() {
+	    public void actionPerformed(ActionEvent e) {
+		System.exit(0);
+	    }
+	}
+	);
+
+	createOptionsMenu(menuBar);
+	return menuBar;
+    }
+
+    void createOptionsMenu(JMenuBar menuBar) {
+	JMenu optionMenu = (JMenu)menuBar.add(new JMenu("Dialogs"));
+        optionMenu.setMnemonic('D');
+	JMenuItem item;
+	item = new JMenuItem("Message Dialog");
+	item.addActionListener(new ActionListener() {
+	    public void actionPerformed(ActionEvent e) {
+		JOptionPane.showMessageDialog(JHOptionTest.this, "Plain message");
+	    }
+	});
+	optionMenu.add(item);
+
+	item = new JMenuItem("Warning Dialog");
+	item.addActionListener(new ActionListener() {
+	    public void actionPerformed(ActionEvent e) {
+		JOptionPane.showMessageDialog(JHOptionTest.this, "Example Warning",
+				    "Warning", JOptionPane.WARNING_MESSAGE);
+	    }
+	});
+	optionMenu.add(item);
+
+	item = new JMenuItem("Confirmation Dialog");
+	item.addActionListener(new ActionListener() {
+	    public void actionPerformed(ActionEvent e) {
+		int        result;
+		result = JOptionPane.showConfirmDialog(JHOptionTest.this, "Is SWING cool?");
+		if(result == JOptionPane.YES_OPTION)
+		    JOptionPane.showMessageDialog(JHOptionTest.this, "All right!");
+		else if(result == JOptionPane.NO_OPTION)
+		    JOptionPane.showMessageDialog(JHOptionTest.this, "That is too bad, please send us email describing what you don't like and how we can change it.");
+	    }
+	});
+	optionMenu.add(item);
+
+	item = new JMenuItem("Input Dialog");
+	item.addActionListener(new ActionListener() {
+	    public void actionPerformed(ActionEvent e) {
+		String          result;
+
+		result = JOptionPane.showInputDialog(JHOptionTest.this, "Please enter your name:");
+		if(result != null) {
+		    Object[] message = new Object[2];
+		    message[0] = "Thank you for using SWING ";
+		    message[1] = result;
+		    JOptionPane.showMessageDialog(JHOptionTest.this, message);
+		}
+	    }
+	});
+	optionMenu.add(item);
+
+	item = new JMenuItem("Message Help Dialog");
+	item.addActionListener(new ActionListener() {
+	    public void actionPerformed(ActionEvent e) {
+		int result;
+		result = HelpUtilities.showMessageDialog(JHOptionTest.this,
+							 "Plain message",
+							 "Message",
+							 HelpUtilities.DEFAULT_HELP_OPTION, 
+							 JOptionPane.INFORMATION_MESSAGE,
+							 null);
+		if (result == HelpUtilities.HELP_OPTION)
+		    JOptionPane.showMessageDialog(JHOptionTest.this, "Help NYI");
+	    }
+	});
+	optionMenu.add(item);
+
+	item = new JMenuItem("Confirmaion YES_NO_HELP Dialog");
+	item.addActionListener(new ActionListener() {
+	    public void actionPerformed(ActionEvent e) {
+		int        result;
+		result = HelpUtilities.showConfirmDialog(JHOptionTest.this,
+						       "Is SWING cool?",
+						       "Swing Confirmation",
+						       HelpUtilities.YES_NO_HELP_OPTION);
+		if(result == HelpUtilities.YES_OPTION)
+		    JOptionPane.showMessageDialog(JHOptionTest.this, "All right!");
+		else if(result == HelpUtilities.NO_OPTION)
+		    JOptionPane.showMessageDialog(JHOptionTest.this, "That is too bad, please send us email describing what you don't like and how we can change it.");
+		else if (result == HelpUtilities.HELP_OPTION)
+		    JOptionPane.showMessageDialog(JHOptionTest.this, "Help NYI");
+
+	    }
+	});
+	optionMenu.add(item);
+
+	item = new JMenuItem("Confirmaion YES_NO_CANCEL_HELP Dialog");
+	item.addActionListener(new ActionListener() {
+	    public void actionPerformed(ActionEvent e) {
+		int        result;
+		result = HelpUtilities.showConfirmDialog(JHOptionTest.this,
+						       "Is SWING cool?",
+						       "Swing Confirmation",
+						       HelpUtilities.YES_NO_CANCEL_HELP_OPTION);
+		if(result == HelpUtilities.YES_OPTION)
+		    JOptionPane.showMessageDialog(JHOptionTest.this, "All right!");
+		else if(result == HelpUtilities.NO_OPTION)
+		    JOptionPane.showMessageDialog(JHOptionTest.this, "That is too bad, please send us email describing what you don't like and how we can change it.");
+		else if (result == HelpUtilities.HELP_OPTION)
+		    JOptionPane.showMessageDialog(JHOptionTest.this, "Help NYI");
+
+	    }
+	});
+	optionMenu.add(item);
+
+
+	/* later when working
+	item = new JMenuItem("Input Help Dialog");
+	item.addActionListener(new ActionListener() {
+	    public void actionPerformed(ActionEvent e) {
+		Object          result;
+
+		result = HelpUtilities.showInputDialog(JHOptionTest.this,
+						     "Please enter your name:",
+						     "Input",
+						     HelpUtilities.OK_CANCEL_HELP_OPTION,
+						     JOptionPane.QUESTION_MESSAGE,
+						     null, null, null);
+		if (result instanceof Integer) {
+		    JOptionPane.showMessageDialog(JHOptionTest.this, "Help NYI");
+		} else {
+		    if(result != null) {
+			Object[] message = new Object[2];
+			message[0] = "Thank you for using SWING ";
+			message[1] = (String) result;
+			JOptionPane.showMessageDialog(JHOptionTest.this, message);
+		    }
+		}
+	    }
+	});
+	optionMenu.add(item);
+	*/
+
+	item = new JMenuItem("Component Dialog");
+	item.addActionListener(new ActionListener() {
+	    public void actionPerformed(ActionEvent e) {
+		Object[]      message = new Object[4];
+                JComboBox cb = new JComboBox();
+                cb.addItem("One");
+                cb.addItem("Two");
+                cb.addItem("Three");
+		message[0] = "JOptionPane can contain any number of components, and any number options.";
+		message[1] = new JButton("a button");
+		message[2] = new JTextField("a text field");
+                message[3] = cb;
+                
+
+		String[]      options = { "Option 1", "Option 2", "Option 3",
+					  "Option 4" };
+		JOptionPane.showOptionDialog(JHOptionTest.this, message, "Example", JOptionPane.DEFAULT_OPTION, JOptionPane.INFORMATION_MESSAGE, null, options, options[1]);
+	    }
+	});
+	optionMenu.add(item);
+    }
+	
+
+    public static void main(String[] args) {
+
+	WindowListener l = new WindowAdapter() {
+	    public void windowClosing(WindowEvent e) {System.exit(0);}
+	};
+
+	frame = new JFrame("JHOptionTest");
+	frame.addWindowListener(l);
+
+	JOptionPane.setRootFrame(frame);
+
+	// show the frame
+	frame.setSize(INITIAL_WIDTH, INITIAL_HEIGHT);
+	Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
+	frame.setLocation(screenSize.width/2 - INITIAL_WIDTH/2,
+			  screenSize.height/2 - INITIAL_HEIGHT/2);
+	frame.show();
+
+        frame.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
+
+	JHOptionTest sw = new JHOptionTest();
+	frame.getContentPane().removeAll();
+	frame.getContentPane().setLayout(new BorderLayout());
+	frame.getContentPane().add(sw, BorderLayout.CENTER);
+	frame.setLocation(screenSize.width/2 - WIDTH/2,
+			  screenSize.height/2 - HEIGHT/2);
+
+	frame.setSize(WIDTH, HEIGHT);
+	frame.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
+
+	frame.validate();
+	frame.repaint();
+    }
+
+
+}
+